aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 11:59:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 11:59:42 -0400
commit22e12bbc9bc38c6d0bd541d061a0f547596fc19d (patch)
tree39b93f43b482c5b4cb9d99933384a8a7fcb85d71
parent19426a8f810752b4218e59b1e2187f33e255f7bc (diff)
parent86ff9baadf16c8a1b452d72f5585be63457d9b15 (diff)
Merge branch 'timers-ptp-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-ptp-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: ptp: Fix dp83640 build warning when building statically ptp: Added a clock driver for the National Semiconductor PHYTER. ptp: Added a clock driver for the IXP46x. ptp: Added a clock that uses the eTSEC found on the MPC85xx. ptp: Added a brand new class driver for ptp clocks.
-rw-r--r--Documentation/ABI/testing/sysfs-ptp98
-rw-r--r--Documentation/devicetree/bindings/net/fsl-tsec-phy.txt54
-rw-r--r--Documentation/ptp/ptp.txt89
-rw-r--r--Documentation/ptp/testptp.c381
-rw-r--r--Documentation/ptp/testptp.mk33
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h78
-rw-r--r--arch/powerpc/boot/dts/mpc8313erdb.dts13
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds.dts13
-rw-r--r--arch/powerpc/boot/dts/p2020ds.dts13
-rw-r--r--arch/powerpc/boot/dts/p2020rdb.dts13
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/arm/ixp4xx_eth.c195
-rw-r--r--drivers/net/gianfar_ptp.c588
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/dp83640.c1100
-rw-r--r--drivers/net/phy/dp83640_reg.h267
-rw-r--r--drivers/ptp/Kconfig75
-rw-r--r--drivers/ptp/Makefile7
-rw-r--r--drivers/ptp/ptp_chardev.c159
-rw-r--r--drivers/ptp/ptp_clock.c343
-rw-r--r--drivers/ptp/ptp_ixp46x.c332
-rw-r--r--drivers/ptp/ptp_private.h92
-rw-r--r--drivers/ptp/ptp_sysfs.c230
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/ptp_classify.h7
-rw-r--r--include/linux/ptp_clock.h84
-rw-r--r--include/linux/ptp_clock_kernel.h139
29 files changed, 4406 insertions, 3 deletions
diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp
new file mode 100644
index 000000000000..d40d2b550502
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-ptp
@@ -0,0 +1,98 @@
1What: /sys/class/ptp/
2Date: September 2010
3Contact: Richard Cochran <richardcochran@gmail.com>
4Description:
5 This directory contains files and directories
6 providing a standardized interface to the ancillary
7 features of PTP hardware clocks.
8
9What: /sys/class/ptp/ptpN/
10Date: September 2010
11Contact: Richard Cochran <richardcochran@gmail.com>
12Description:
13 This directory contains the attributes of the Nth PTP
14 hardware clock registered into the PTP class driver
15 subsystem.
16
17What: /sys/class/ptp/ptpN/clock_name
18Date: September 2010
19Contact: Richard Cochran <richardcochran@gmail.com>
20Description:
21 This file contains the name of the PTP hardware clock
22 as a human readable string.
23
24What: /sys/class/ptp/ptpN/max_adjustment
25Date: September 2010
26Contact: Richard Cochran <richardcochran@gmail.com>
27Description:
28 This file contains the PTP hardware clock's maximum
29 frequency adjustment value (a positive integer) in
30 parts per billion.
31
32What: /sys/class/ptp/ptpN/n_alarms
33Date: September 2010
34Contact: Richard Cochran <richardcochran@gmail.com>
35Description:
36 This file contains the number of periodic or one shot
37 alarms offer by the PTP hardware clock.
38
39What: /sys/class/ptp/ptpN/n_external_timestamps
40Date: September 2010
41Contact: Richard Cochran <richardcochran@gmail.com>
42Description:
43 This file contains the number of external timestamp
44 channels offered by the PTP hardware clock.
45
46What: /sys/class/ptp/ptpN/n_periodic_outputs
47Date: September 2010
48Contact: Richard Cochran <richardcochran@gmail.com>
49Description:
50 This file contains the number of programmable periodic
51 output channels offered by the PTP hardware clock.
52
53What: /sys/class/ptp/ptpN/pps_avaiable
54Date: September 2010
55Contact: Richard Cochran <richardcochran@gmail.com>
56Description:
57 This file indicates whether the PTP hardware clock
58 supports a Pulse Per Second to the host CPU. Reading
59 "1" means that the PPS is supported, while "0" means
60 not supported.
61
62What: /sys/class/ptp/ptpN/extts_enable
63Date: September 2010
64Contact: Richard Cochran <richardcochran@gmail.com>
65Description:
66 This write-only file enables or disables external
67 timestamps. To enable external timestamps, write the
68 channel index followed by a "1" into the file.
69 To disable external timestamps, write the channel
70 index followed by a "0" into the file.
71
72What: /sys/class/ptp/ptpN/fifo
73Date: September 2010
74Contact: Richard Cochran <richardcochran@gmail.com>
75Description:
76 This file provides timestamps on external events, in
77 the form of three integers: channel index, seconds,
78 and nanoseconds.
79
80What: /sys/class/ptp/ptpN/period
81Date: September 2010
82Contact: Richard Cochran <richardcochran@gmail.com>
83Description:
84 This write-only file enables or disables periodic
85 outputs. To enable a periodic output, write five
86 integers into the file: channel index, start time
87 seconds, start time nanoseconds, period seconds, and
88 period nanoseconds. To disable a periodic output, set
89 all the seconds and nanoseconds values to zero.
90
91What: /sys/class/ptp/ptpN/pps_enable
92Date: September 2010
93Contact: Richard Cochran <richardcochran@gmail.com>
94Description:
95 This write-only file enables or disables delivery of
96 PPS events to the Linux PPS subsystem. To enable PPS
97 events, write a "1" into the file. To disable events,
98 write a "0" into the file.
diff --git a/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt b/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
index edb7ae19e868..2c6be0377f55 100644
--- a/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
+++ b/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
@@ -74,3 +74,57 @@ Example:
74 interrupt-parent = <&mpic>; 74 interrupt-parent = <&mpic>;
75 phy-handle = <&phy0> 75 phy-handle = <&phy0>
76 }; 76 };
77
78* Gianfar PTP clock nodes
79
80General Properties:
81
82 - compatible Should be "fsl,etsec-ptp"
83 - reg Offset and length of the register set for the device
84 - interrupts There should be at least two interrupts. Some devices
85 have as many as four PTP related interrupts.
86
87Clock Properties:
88
89 - fsl,tclk-period Timer reference clock period in nanoseconds.
90 - fsl,tmr-prsc Prescaler, divides the output clock.
91 - fsl,tmr-add Frequency compensation value.
92 - fsl,tmr-fiper1 Fixed interval period pulse generator.
93 - fsl,tmr-fiper2 Fixed interval period pulse generator.
94 - fsl,max-adj Maximum frequency adjustment in parts per billion.
95
96 These properties set the operational parameters for the PTP
97 clock. You must choose these carefully for the clock to work right.
98 Here is how to figure good values:
99
100 TimerOsc = system clock MHz
101 tclk_period = desired clock period nanoseconds
102 NominalFreq = 1000 / tclk_period MHz
103 FreqDivRatio = TimerOsc / NominalFreq (must be greater that 1.0)
104 tmr_add = ceil(2^32 / FreqDivRatio)
105 OutputClock = NominalFreq / tmr_prsc MHz
106 PulseWidth = 1 / OutputClock microseconds
107 FiperFreq1 = desired frequency in Hz
108 FiperDiv1 = 1000000 * OutputClock / FiperFreq1
109 tmr_fiper1 = tmr_prsc * tclk_period * FiperDiv1 - tclk_period
110 max_adj = 1000000000 * (FreqDivRatio - 1.0) - 1
111
112 The calculation for tmr_fiper2 is the same as for tmr_fiper1. The
113 driver expects that tmr_fiper1 will be correctly set to produce a 1
114 Pulse Per Second (PPS) signal, since this will be offered to the PPS
115 subsystem to synchronize the Linux clock.
116
117Example:
118
119 ptp_clock@24E00 {
120 compatible = "fsl,etsec-ptp";
121 reg = <0x24E00 0xB0>;
122 interrupts = <12 0x8 13 0x8>;
123 interrupt-parent = < &ipic >;
124 fsl,tclk-period = <10>;
125 fsl,tmr-prsc = <100>;
126 fsl,tmr-add = <0x999999A4>;
127 fsl,tmr-fiper1 = <0x3B9AC9F6>;
128 fsl,tmr-fiper2 = <0x00018696>;
129 fsl,max-adj = <659999998>;
130 };
diff --git a/Documentation/ptp/ptp.txt b/Documentation/ptp/ptp.txt
new file mode 100644
index 000000000000..ae8fef86b832
--- /dev/null
+++ b/Documentation/ptp/ptp.txt
@@ -0,0 +1,89 @@
1
2* PTP hardware clock infrastructure for Linux
3
4 This patch set introduces support for IEEE 1588 PTP clocks in
5 Linux. Together with the SO_TIMESTAMPING socket options, this
6 presents a standardized method for developing PTP user space
7 programs, synchronizing Linux with external clocks, and using the
8 ancillary features of PTP hardware clocks.
9
10 A new class driver exports a kernel interface for specific clock
11 drivers and a user space interface. The infrastructure supports a
12 complete set of PTP hardware clock functionality.
13
14 + Basic clock operations
15 - Set time
16 - Get time
17 - Shift the clock by a given offset atomically
18 - Adjust clock frequency
19
20 + Ancillary clock features
21 - One short or periodic alarms, with signal delivery to user program
22 - Time stamp external events
23 - Period output signals configurable from user space
24 - Synchronization of the Linux system time via the PPS subsystem
25
26** PTP hardware clock kernel API
27
28 A PTP clock driver registers itself with the class driver. The
29 class driver handles all of the dealings with user space. The
30 author of a clock driver need only implement the details of
31 programming the clock hardware. The clock driver notifies the class
32 driver of asynchronous events (alarms and external time stamps) via
33 a simple message passing interface.
34
35 The class driver supports multiple PTP clock drivers. In normal use
36 cases, only one PTP clock is needed. However, for testing and
37 development, it can be useful to have more than one clock in a
38 single system, in order to allow performance comparisons.
39
40** PTP hardware clock user space API
41
42 The class driver also creates a character device for each
43 registered clock. User space can use an open file descriptor from
44 the character device as a POSIX clock id and may call
45 clock_gettime, clock_settime, and clock_adjtime. These calls
46 implement the basic clock operations.
47
48 User space programs may control the clock using standardized
49 ioctls. A program may query, enable, configure, and disable the
50 ancillary clock features. User space can receive time stamped
51 events via blocking read() and poll(). One shot and periodic
52 signals may be configured via the POSIX timer_settime() system
53 call.
54
55** Writing clock drivers
56
57 Clock drivers include include/linux/ptp_clock_kernel.h and register
58 themselves by presenting a 'struct ptp_clock_info' to the
59 registration method. Clock drivers must implement all of the
60 functions in the interface. If a clock does not offer a particular
61 ancillary feature, then the driver should just return -EOPNOTSUPP
62 from those functions.
63
64 Drivers must ensure that all of the methods in interface are
65 reentrant. Since most hardware implementations treat the time value
66 as a 64 bit integer accessed as two 32 bit registers, drivers
67 should use spin_lock_irqsave/spin_unlock_irqrestore to protect
68 against concurrent access. This locking cannot be accomplished in
69 class driver, since the lock may also be needed by the clock
70 driver's interrupt service routine.
71
72** Supported hardware
73
74 + Freescale eTSEC gianfar
75 - 2 Time stamp external triggers, programmable polarity (opt. interrupt)
76 - 2 Alarm registers (optional interrupt)
77 - 3 Periodic signals (optional interrupt)
78
79 + National DP83640
80 - 6 GPIOs programmable as inputs or outputs
81 - 6 GPIOs with dedicated functions (LED/JTAG/clock) can also be
82 used as general inputs or outputs
83 - GPIO inputs can time stamp external triggers
84 - GPIO outputs can produce periodic signals
85 - 1 interrupt pin
86
87 + Intel IXP465
88 - Auxiliary Slave/Master Mode Snapshot (optional interrupt)
89 - Target Time (optional interrupt)
diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c
new file mode 100644
index 000000000000..f59ded066108
--- /dev/null
+++ b/Documentation/ptp/testptp.c
@@ -0,0 +1,381 @@
1/*
2 * PTP 1588 clock support - User space test program
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <errno.h>
21#include <fcntl.h>
22#include <math.h>
23#include <signal.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/ioctl.h>
28#include <sys/mman.h>
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <sys/timex.h>
32#include <sys/types.h>
33#include <time.h>
34#include <unistd.h>
35
36#include <linux/ptp_clock.h>
37
38#define DEVICE "/dev/ptp0"
39
40#ifndef ADJ_SETOFFSET
41#define ADJ_SETOFFSET 0x0100
42#endif
43
44#ifndef CLOCK_INVALID
45#define CLOCK_INVALID -1
46#endif
47
48/* When glibc offers the syscall, this will go away. */
49#include <sys/syscall.h>
50static int clock_adjtime(clockid_t id, struct timex *tx)
51{
52 return syscall(__NR_clock_adjtime, id, tx);
53}
54
55static clockid_t get_clockid(int fd)
56{
57#define CLOCKFD 3
58#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
59
60 return FD_TO_CLOCKID(fd);
61}
62
63static void handle_alarm(int s)
64{
65 printf("received signal %d\n", s);
66}
67
68static int install_handler(int signum, void (*handler)(int))
69{
70 struct sigaction action;
71 sigset_t mask;
72
73 /* Unblock the signal. */
74 sigemptyset(&mask);
75 sigaddset(&mask, signum);
76 sigprocmask(SIG_UNBLOCK, &mask, NULL);
77
78 /* Install the signal handler. */
79 action.sa_handler = handler;
80 action.sa_flags = 0;
81 sigemptyset(&action.sa_mask);
82 sigaction(signum, &action, NULL);
83
84 return 0;
85}
86
87static long ppb_to_scaled_ppm(int ppb)
88{
89 /*
90 * The 'freq' field in the 'struct timex' is in parts per
91 * million, but with a 16 bit binary fractional field.
92 * Instead of calculating either one of
93 *
94 * scaled_ppm = (ppb / 1000) << 16 [1]
95 * scaled_ppm = (ppb << 16) / 1000 [2]
96 *
97 * we simply use double precision math, in order to avoid the
98 * truncation in [1] and the possible overflow in [2].
99 */
100 return (long) (ppb * 65.536);
101}
102
103static void usage(char *progname)
104{
105 fprintf(stderr,
106 "usage: %s [options]\n"
107 " -a val request a one-shot alarm after 'val' seconds\n"
108 " -A val request a periodic alarm every 'val' seconds\n"
109 " -c query the ptp clock's capabilities\n"
110 " -d name device to open\n"
111 " -e val read 'val' external time stamp events\n"
112 " -f val adjust the ptp clock frequency by 'val' ppb\n"
113 " -g get the ptp clock time\n"
114 " -h prints this message\n"
115 " -p val enable output with a period of 'val' nanoseconds\n"
116 " -P val enable or disable (val=1|0) the system clock PPS\n"
117 " -s set the ptp clock time from the system time\n"
118 " -S set the system time from the ptp clock time\n"
119 " -t val shift the ptp clock time by 'val' seconds\n",
120 progname);
121}
122
123int main(int argc, char *argv[])
124{
125 struct ptp_clock_caps caps;
126 struct ptp_extts_event event;
127 struct ptp_extts_request extts_request;
128 struct ptp_perout_request perout_request;
129 struct timespec ts;
130 struct timex tx;
131
132 static timer_t timerid;
133 struct itimerspec timeout;
134 struct sigevent sigevent;
135
136 char *progname;
137 int c, cnt, fd;
138
139 char *device = DEVICE;
140 clockid_t clkid;
141 int adjfreq = 0x7fffffff;
142 int adjtime = 0;
143 int capabilities = 0;
144 int extts = 0;
145 int gettime = 0;
146 int oneshot = 0;
147 int periodic = 0;
148 int perout = -1;
149 int pps = -1;
150 int settime = 0;
151
152 progname = strrchr(argv[0], '/');
153 progname = progname ? 1+progname : argv[0];
154 while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghp:P:sSt:v"))) {
155 switch (c) {
156 case 'a':
157 oneshot = atoi(optarg);
158 break;
159 case 'A':
160 periodic = atoi(optarg);
161 break;
162 case 'c':
163 capabilities = 1;
164 break;
165 case 'd':
166 device = optarg;
167 break;
168 case 'e':
169 extts = atoi(optarg);
170 break;
171 case 'f':
172 adjfreq = atoi(optarg);
173 break;
174 case 'g':
175 gettime = 1;
176 break;
177 case 'p':
178 perout = atoi(optarg);
179 break;
180 case 'P':
181 pps = atoi(optarg);
182 break;
183 case 's':
184 settime = 1;
185 break;
186 case 'S':
187 settime = 2;
188 break;
189 case 't':
190 adjtime = atoi(optarg);
191 break;
192 case 'h':
193 usage(progname);
194 return 0;
195 case '?':
196 default:
197 usage(progname);
198 return -1;
199 }
200 }
201
202 fd = open(device, O_RDWR);
203 if (fd < 0) {
204 fprintf(stderr, "opening %s: %s\n", device, strerror(errno));
205 return -1;
206 }
207
208 clkid = get_clockid(fd);
209 if (CLOCK_INVALID == clkid) {
210 fprintf(stderr, "failed to read clock id\n");
211 return -1;
212 }
213
214 if (capabilities) {
215 if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
216 perror("PTP_CLOCK_GETCAPS");
217 } else {
218 printf("capabilities:\n"
219 " %d maximum frequency adjustment (ppb)\n"
220 " %d programmable alarms\n"
221 " %d external time stamp channels\n"
222 " %d programmable periodic signals\n"
223 " %d pulse per second\n",
224 caps.max_adj,
225 caps.n_alarm,
226 caps.n_ext_ts,
227 caps.n_per_out,
228 caps.pps);
229 }
230 }
231
232 if (0x7fffffff != adjfreq) {
233 memset(&tx, 0, sizeof(tx));
234 tx.modes = ADJ_FREQUENCY;
235 tx.freq = ppb_to_scaled_ppm(adjfreq);
236 if (clock_adjtime(clkid, &tx)) {
237 perror("clock_adjtime");
238 } else {
239 puts("frequency adjustment okay");
240 }
241 }
242
243 if (adjtime) {
244 memset(&tx, 0, sizeof(tx));
245 tx.modes = ADJ_SETOFFSET;
246 tx.time.tv_sec = adjtime;
247 tx.time.tv_usec = 0;
248 if (clock_adjtime(clkid, &tx) < 0) {
249 perror("clock_adjtime");
250 } else {
251 puts("time shift okay");
252 }
253 }
254
255 if (gettime) {
256 if (clock_gettime(clkid, &ts)) {
257 perror("clock_gettime");
258 } else {
259 printf("clock time: %ld.%09ld or %s",
260 ts.tv_sec, ts.tv_nsec, ctime(&ts.tv_sec));
261 }
262 }
263
264 if (settime == 1) {
265 clock_gettime(CLOCK_REALTIME, &ts);
266 if (clock_settime(clkid, &ts)) {
267 perror("clock_settime");
268 } else {
269 puts("set time okay");
270 }
271 }
272
273 if (settime == 2) {
274 clock_gettime(clkid, &ts);
275 if (clock_settime(CLOCK_REALTIME, &ts)) {
276 perror("clock_settime");
277 } else {
278 puts("set time okay");
279 }
280 }
281
282 if (extts) {
283 memset(&extts_request, 0, sizeof(extts_request));
284 extts_request.index = 0;
285 extts_request.flags = PTP_ENABLE_FEATURE;
286 if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
287 perror("PTP_EXTTS_REQUEST");
288 extts = 0;
289 } else {
290 puts("external time stamp request okay");
291 }
292 for (; extts; extts--) {
293 cnt = read(fd, &event, sizeof(event));
294 if (cnt != sizeof(event)) {
295 perror("read");
296 break;
297 }
298 printf("event index %u at %lld.%09u\n", event.index,
299 event.t.sec, event.t.nsec);
300 fflush(stdout);
301 }
302 /* Disable the feature again. */
303 extts_request.flags = 0;
304 if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
305 perror("PTP_EXTTS_REQUEST");
306 }
307 }
308
309 if (oneshot) {
310 install_handler(SIGALRM, handle_alarm);
311 /* Create a timer. */
312 sigevent.sigev_notify = SIGEV_SIGNAL;
313 sigevent.sigev_signo = SIGALRM;
314 if (timer_create(clkid, &sigevent, &timerid)) {
315 perror("timer_create");
316 return -1;
317 }
318 /* Start the timer. */
319 memset(&timeout, 0, sizeof(timeout));
320 timeout.it_value.tv_sec = oneshot;
321 if (timer_settime(timerid, 0, &timeout, NULL)) {
322 perror("timer_settime");
323 return -1;
324 }
325 pause();
326 timer_delete(timerid);
327 }
328
329 if (periodic) {
330 install_handler(SIGALRM, handle_alarm);
331 /* Create a timer. */
332 sigevent.sigev_notify = SIGEV_SIGNAL;
333 sigevent.sigev_signo = SIGALRM;
334 if (timer_create(clkid, &sigevent, &timerid)) {
335 perror("timer_create");
336 return -1;
337 }
338 /* Start the timer. */
339 memset(&timeout, 0, sizeof(timeout));
340 timeout.it_interval.tv_sec = periodic;
341 timeout.it_value.tv_sec = periodic;
342 if (timer_settime(timerid, 0, &timeout, NULL)) {
343 perror("timer_settime");
344 return -1;
345 }
346 while (1) {
347 pause();
348 }
349 timer_delete(timerid);
350 }
351
352 if (perout >= 0) {
353 if (clock_gettime(clkid, &ts)) {
354 perror("clock_gettime");
355 return -1;
356 }
357 memset(&perout_request, 0, sizeof(perout_request));
358 perout_request.index = 0;
359 perout_request.start.sec = ts.tv_sec + 2;
360 perout_request.start.nsec = 0;
361 perout_request.period.sec = 0;
362 perout_request.period.nsec = perout;
363 if (ioctl(fd, PTP_PEROUT_REQUEST, &perout_request)) {
364 perror("PTP_PEROUT_REQUEST");
365 } else {
366 puts("periodic output request okay");
367 }
368 }
369
370 if (pps != -1) {
371 int enable = pps ? 1 : 0;
372 if (ioctl(fd, PTP_ENABLE_PPS, enable)) {
373 perror("PTP_ENABLE_PPS");
374 } else {
375 puts("pps for system time request okay");
376 }
377 }
378
379 close(fd);
380 return 0;
381}
diff --git a/Documentation/ptp/testptp.mk b/Documentation/ptp/testptp.mk
new file mode 100644
index 000000000000..4ef2d9755421
--- /dev/null
+++ b/Documentation/ptp/testptp.mk
@@ -0,0 +1,33 @@
1# PTP 1588 clock support - User space test program
2#
3# Copyright (C) 2010 OMICRON electronics GmbH
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19CC = $(CROSS_COMPILE)gcc
20INC = -I$(KBUILD_OUTPUT)/usr/include
21CFLAGS = -Wall $(INC)
22LDLIBS = -lrt
23PROGS = testptp
24
25all: $(PROGS)
26
27testptp: testptp.o
28
29clean:
30 rm -f testptp.o
31
32distclean: clean
33 rm -f $(PROGS)
diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
new file mode 100644
index 000000000000..292d55ed2113
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
@@ -0,0 +1,78 @@
1/*
2 * PTP 1588 clock using the IXP46X
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef _IXP46X_TS_H_
22#define _IXP46X_TS_H_
23
24#define DEFAULT_ADDEND 0xF0000029
25#define TICKS_NS_SHIFT 4
26
27struct ixp46x_channel_ctl {
28 u32 ch_control; /* 0x40 Time Synchronization Channel Control */
29 u32 ch_event; /* 0x44 Time Synchronization Channel Event */
30 u32 tx_snap_lo; /* 0x48 Transmit Snapshot Low Register */
31 u32 tx_snap_hi; /* 0x4C Transmit Snapshot High Register */
32 u32 rx_snap_lo; /* 0x50 Receive Snapshot Low Register */
33 u32 rx_snap_hi; /* 0x54 Receive Snapshot High Register */
34 u32 src_uuid_lo; /* 0x58 Source UUID0 Low Register */
35 u32 src_uuid_hi; /* 0x5C Sequence Identifier/Source UUID0 High */
36};
37
38struct ixp46x_ts_regs {
39 u32 control; /* 0x00 Time Sync Control Register */
40 u32 event; /* 0x04 Time Sync Event Register */
41 u32 addend; /* 0x08 Time Sync Addend Register */
42 u32 accum; /* 0x0C Time Sync Accumulator Register */
43 u32 test; /* 0x10 Time Sync Test Register */
44 u32 unused; /* 0x14 */
45 u32 rsystime_lo; /* 0x18 RawSystemTime_Low Register */
46 u32 rsystime_hi; /* 0x1C RawSystemTime_High Register */
47 u32 systime_lo; /* 0x20 SystemTime_Low Register */
48 u32 systime_hi; /* 0x24 SystemTime_High Register */
49 u32 trgt_lo; /* 0x28 TargetTime_Low Register */
50 u32 trgt_hi; /* 0x2C TargetTime_High Register */
51 u32 asms_lo; /* 0x30 Auxiliary Slave Mode Snapshot Low */
52 u32 asms_hi; /* 0x34 Auxiliary Slave Mode Snapshot High */
53 u32 amms_lo; /* 0x38 Auxiliary Master Mode Snapshot Low */
54 u32 amms_hi; /* 0x3C Auxiliary Master Mode Snapshot High */
55
56 struct ixp46x_channel_ctl channel[3];
57};
58
59/* 0x00 Time Sync Control Register Bits */
60#define TSCR_AMM (1<<3)
61#define TSCR_ASM (1<<2)
62#define TSCR_TTM (1<<1)
63#define TSCR_RST (1<<0)
64
65/* 0x04 Time Sync Event Register Bits */
66#define TSER_SNM (1<<3)
67#define TSER_SNS (1<<2)
68#define TTIPEND (1<<1)
69
70/* 0x40 Time Synchronization Channel Control Register Bits */
71#define MASTER_MODE (1<<0)
72#define TIMESTAMP_ALL (1<<1)
73
74/* 0x44 Time Synchronization Channel Event Register Bits */
75#define TX_SNAPSHOT_LOCKED (1<<0)
76#define RX_SNAPSHOT_LOCKED (1<<1)
77
78#endif
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 761faa7b6964..ac1eb320c7b4 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -176,6 +176,19 @@
176 sleep = <&pmc 0x00300000>; 176 sleep = <&pmc 0x00300000>;
177 }; 177 };
178 178
179 ptp_clock@24E00 {
180 compatible = "fsl,etsec-ptp";
181 reg = <0x24E00 0xB0>;
182 interrupts = <12 0x8 13 0x8>;
183 interrupt-parent = < &ipic >;
184 fsl,tclk-period = <10>;
185 fsl,tmr-prsc = <100>;
186 fsl,tmr-add = <0x999999A4>;
187 fsl,tmr-fiper1 = <0x3B9AC9F6>;
188 fsl,tmr-fiper2 = <0x00018696>;
189 fsl,max-adj = <659999998>;
190 };
191
179 enet0: ethernet@24000 { 192 enet0: ethernet@24000 {
180 #address-cells = <1>; 193 #address-cells = <1>;
181 #size-cells = <1>; 194 #size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index cafc1285c140..f6c04d25e916 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -324,6 +324,19 @@
324 }; 324 };
325 }; 325 };
326 326
327 ptp_clock@24E00 {
328 compatible = "fsl,etsec-ptp";
329 reg = <0x24E00 0xB0>;
330 interrupts = <68 2 69 2 70 2 71 2>;
331 interrupt-parent = < &mpic >;
332 fsl,tclk-period = <5>;
333 fsl,tmr-prsc = <200>;
334 fsl,tmr-add = <0xAAAAAAAB>;
335 fsl,tmr-fiper1 = <0x3B9AC9FB>;
336 fsl,tmr-fiper2 = <0x3B9AC9FB>;
337 fsl,max-adj = <499999999>;
338 };
339
327 enet0: ethernet@24000 { 340 enet0: ethernet@24000 {
328 #address-cells = <1>; 341 #address-cells = <1>;
329 #size-cells = <1>; 342 #size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/p2020ds.dts b/arch/powerpc/boot/dts/p2020ds.dts
index 2bcf3683d223..dae403100f2f 100644
--- a/arch/powerpc/boot/dts/p2020ds.dts
+++ b/arch/powerpc/boot/dts/p2020ds.dts
@@ -178,6 +178,19 @@
178 178
179 }; 179 };
180 180
181 ptp_clock@24E00 {
182 compatible = "fsl,etsec-ptp";
183 reg = <0x24E00 0xB0>;
184 interrupts = <68 2 69 2 70 2>;
185 interrupt-parent = < &mpic >;
186 fsl,tclk-period = <5>;
187 fsl,tmr-prsc = <200>;
188 fsl,tmr-add = <0xCCCCCCCD>;
189 fsl,tmr-fiper1 = <0x3B9AC9FB>;
190 fsl,tmr-fiper2 = <0x0001869B>;
191 fsl,max-adj = <249999999>;
192 };
193
181 enet0: ethernet@24000 { 194 enet0: ethernet@24000 {
182 tbi-handle = <&tbi0>; 195 tbi-handle = <&tbi0>;
183 phy-handle = <&phy0>; 196 phy-handle = <&phy0>;
diff --git a/arch/powerpc/boot/dts/p2020rdb.dts b/arch/powerpc/boot/dts/p2020rdb.dts
index 3782a58f13be..1d7a05f3021e 100644
--- a/arch/powerpc/boot/dts/p2020rdb.dts
+++ b/arch/powerpc/boot/dts/p2020rdb.dts
@@ -224,6 +224,19 @@
224 status = "disabled"; 224 status = "disabled";
225 }; 225 };
226 226
227 ptp_clock@24E00 {
228 compatible = "fsl,etsec-ptp";
229 reg = <0x24E00 0xB0>;
230 interrupts = <68 2 69 2 70 2>;
231 interrupt-parent = < &mpic >;
232 fsl,tclk-period = <5>;
233 fsl,tmr-prsc = <200>;
234 fsl,tmr-add = <0xCCCCCCCD>;
235 fsl,tmr-fiper1 = <0x3B9AC9FB>;
236 fsl,tmr-fiper2 = <0x0001869B>;
237 fsl,max-adj = <249999999>;
238 };
239
227 enet0: ethernet@24000 { 240 enet0: ethernet@24000 {
228 fixed-link = <1 1 1000 0 0>; 241 fixed-link = <1 1 1000 0 0>;
229 phy-connection-type = "rgmii-id"; 242 phy-connection-type = "rgmii-id";
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 61631edfecc2..3bb154d8c8cc 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -54,6 +54,8 @@ source "drivers/spi/Kconfig"
54 54
55source "drivers/pps/Kconfig" 55source "drivers/pps/Kconfig"
56 56
57source "drivers/ptp/Kconfig"
58
57source "drivers/gpio/Kconfig" 59source "drivers/gpio/Kconfig"
58 60
59source "drivers/w1/Kconfig" 61source "drivers/w1/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index bceb60c85c01..6b17f5864340 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_I2O) += message/
75obj-$(CONFIG_RTC_LIB) += rtc/ 75obj-$(CONFIG_RTC_LIB) += rtc/
76obj-y += i2c/ media/ 76obj-y += i2c/ media/
77obj-$(CONFIG_PPS) += pps/ 77obj-$(CONFIG_PPS) += pps/
78obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
78obj-$(CONFIG_W1) += w1/ 79obj-$(CONFIG_W1) += w1/
79obj-$(CONFIG_POWER_SUPPLY) += power/ 80obj-$(CONFIG_POWER_SUPPLY) += power/
80obj-$(CONFIG_HWMON) += hwmon/ 81obj-$(CONFIG_HWMON) += hwmon/
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 209fbb70619b..776a478e6296 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_ATL2) += atlx/
31obj-$(CONFIG_ATL1E) += atl1e/ 31obj-$(CONFIG_ATL1E) += atl1e/
32obj-$(CONFIG_ATL1C) += atl1c/ 32obj-$(CONFIG_ATL1C) += atl1c/
33obj-$(CONFIG_GIANFAR) += gianfar_driver.o 33obj-$(CONFIG_GIANFAR) += gianfar_driver.o
34obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
34obj-$(CONFIG_TEHUTI) += tehuti.o 35obj-$(CONFIG_TEHUTI) += tehuti.o
35obj-$(CONFIG_ENIC) += enic/ 36obj-$(CONFIG_ENIC) += enic/
36obj-$(CONFIG_JME) += jme.o 37obj-$(CONFIG_JME) += jme.o
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index 9eb9b98a7ae3..de51e8453c13 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -30,9 +30,12 @@
30#include <linux/etherdevice.h> 30#include <linux/etherdevice.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/kernel.h> 32#include <linux/kernel.h>
33#include <linux/net_tstamp.h>
33#include <linux/phy.h> 34#include <linux/phy.h>
34#include <linux/platform_device.h> 35#include <linux/platform_device.h>
36#include <linux/ptp_classify.h>
35#include <linux/slab.h> 37#include <linux/slab.h>
38#include <mach/ixp46x_ts.h>
36#include <mach/npe.h> 39#include <mach/npe.h>
37#include <mach/qmgr.h> 40#include <mach/qmgr.h>
38 41
@@ -67,6 +70,10 @@
67#define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26) 70#define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26)
68#define TXDONE_QUEUE 31 71#define TXDONE_QUEUE 31
69 72
73#define PTP_SLAVE_MODE 1
74#define PTP_MASTER_MODE 2
75#define PORT2CHANNEL(p) NPE_ID(p->id)
76
70/* TX Control Registers */ 77/* TX Control Registers */
71#define TX_CNTRL0_TX_EN 0x01 78#define TX_CNTRL0_TX_EN 0x01
72#define TX_CNTRL0_HALFDUPLEX 0x02 79#define TX_CNTRL0_HALFDUPLEX 0x02
@@ -171,6 +178,8 @@ struct port {
171 int id; /* logical port ID */ 178 int id; /* logical port ID */
172 int speed, duplex; 179 int speed, duplex;
173 u8 firmware[4]; 180 u8 firmware[4];
181 int hwts_tx_en;
182 int hwts_rx_en;
174}; 183};
175 184
176/* NPE message structure */ 185/* NPE message structure */
@@ -246,6 +255,172 @@ static int ports_open;
246static struct port *npe_port_tab[MAX_NPES]; 255static struct port *npe_port_tab[MAX_NPES];
247static struct dma_pool *dma_pool; 256static struct dma_pool *dma_pool;
248 257
258static struct sock_filter ptp_filter[] = {
259 PTP_FILTER
260};
261
262static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
263{
264 u8 *data = skb->data;
265 unsigned int offset;
266 u16 *hi, *id;
267 u32 lo;
268
269 if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
270 return 0;
271
272 offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
273
274 if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid))
275 return 0;
276
277 hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID);
278 id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
279
280 memcpy(&lo, &hi[1], sizeof(lo));
281
282 return (uid_hi == ntohs(*hi) &&
283 uid_lo == ntohl(lo) &&
284 seqid == ntohs(*id));
285}
286
287static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb)
288{
289 struct skb_shared_hwtstamps *shhwtstamps;
290 struct ixp46x_ts_regs *regs;
291 u64 ns;
292 u32 ch, hi, lo, val;
293 u16 uid, seq;
294
295 if (!port->hwts_rx_en)
296 return;
297
298 ch = PORT2CHANNEL(port);
299
300 regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
301
302 val = __raw_readl(&regs->channel[ch].ch_event);
303
304 if (!(val & RX_SNAPSHOT_LOCKED))
305 return;
306
307 lo = __raw_readl(&regs->channel[ch].src_uuid_lo);
308 hi = __raw_readl(&regs->channel[ch].src_uuid_hi);
309
310 uid = hi & 0xffff;
311 seq = (hi >> 16) & 0xffff;
312
313 if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq)))
314 goto out;
315
316 lo = __raw_readl(&regs->channel[ch].rx_snap_lo);
317 hi = __raw_readl(&regs->channel[ch].rx_snap_hi);
318 ns = ((u64) hi) << 32;
319 ns |= lo;
320 ns <<= TICKS_NS_SHIFT;
321
322 shhwtstamps = skb_hwtstamps(skb);
323 memset(shhwtstamps, 0, sizeof(*shhwtstamps));
324 shhwtstamps->hwtstamp = ns_to_ktime(ns);
325out:
326 __raw_writel(RX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
327}
328
329static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
330{
331 struct skb_shared_hwtstamps shhwtstamps;
332 struct ixp46x_ts_regs *regs;
333 struct skb_shared_info *shtx;
334 u64 ns;
335 u32 ch, cnt, hi, lo, val;
336
337 shtx = skb_shinfo(skb);
338 if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && port->hwts_tx_en))
339 shtx->tx_flags |= SKBTX_IN_PROGRESS;
340 else
341 return;
342
343 ch = PORT2CHANNEL(port);
344
345 regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
346
347 /*
348 * This really stinks, but we have to poll for the Tx time stamp.
349 * Usually, the time stamp is ready after 4 to 6 microseconds.
350 */
351 for (cnt = 0; cnt < 100; cnt++) {
352 val = __raw_readl(&regs->channel[ch].ch_event);
353 if (val & TX_SNAPSHOT_LOCKED)
354 break;
355 udelay(1);
356 }
357 if (!(val & TX_SNAPSHOT_LOCKED)) {
358 shtx->tx_flags &= ~SKBTX_IN_PROGRESS;
359 return;
360 }
361
362 lo = __raw_readl(&regs->channel[ch].tx_snap_lo);
363 hi = __raw_readl(&regs->channel[ch].tx_snap_hi);
364 ns = ((u64) hi) << 32;
365 ns |= lo;
366 ns <<= TICKS_NS_SHIFT;
367
368 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
369 shhwtstamps.hwtstamp = ns_to_ktime(ns);
370 skb_tstamp_tx(skb, &shhwtstamps);
371
372 __raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
373}
374
375static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
376{
377 struct hwtstamp_config cfg;
378 struct ixp46x_ts_regs *regs;
379 struct port *port = netdev_priv(netdev);
380 int ch;
381
382 if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
383 return -EFAULT;
384
385 if (cfg.flags) /* reserved for future extensions */
386 return -EINVAL;
387
388 ch = PORT2CHANNEL(port);
389 regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
390
391 switch (cfg.tx_type) {
392 case HWTSTAMP_TX_OFF:
393 port->hwts_tx_en = 0;
394 break;
395 case HWTSTAMP_TX_ON:
396 port->hwts_tx_en = 1;
397 break;
398 default:
399 return -ERANGE;
400 }
401
402 switch (cfg.rx_filter) {
403 case HWTSTAMP_FILTER_NONE:
404 port->hwts_rx_en = 0;
405 break;
406 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
407 port->hwts_rx_en = PTP_SLAVE_MODE;
408 __raw_writel(0, &regs->channel[ch].ch_control);
409 break;
410 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
411 port->hwts_rx_en = PTP_MASTER_MODE;
412 __raw_writel(MASTER_MODE, &regs->channel[ch].ch_control);
413 break;
414 default:
415 return -ERANGE;
416 }
417
418 /* Clear out any old time stamps. */
419 __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED,
420 &regs->channel[ch].ch_event);
421
422 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
423}
249 424
250static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, 425static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
251 int write, u16 cmd) 426 int write, u16 cmd)
@@ -573,6 +748,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
573 748
574 debug_pkt(dev, "eth_poll", skb->data, skb->len); 749 debug_pkt(dev, "eth_poll", skb->data, skb->len);
575 750
751 ixp_rx_timestamp(port, skb);
576 skb->protocol = eth_type_trans(skb, dev); 752 skb->protocol = eth_type_trans(skb, dev);
577 dev->stats.rx_packets++; 753 dev->stats.rx_packets++;
578 dev->stats.rx_bytes += skb->len; 754 dev->stats.rx_bytes += skb->len;
@@ -679,14 +855,12 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
679 return NETDEV_TX_OK; 855 return NETDEV_TX_OK;
680 } 856 }
681 memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); 857 memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
682 dev_kfree_skb(skb);
683#endif 858#endif
684 859
685 phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); 860 phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
686 if (dma_mapping_error(&dev->dev, phys)) { 861 if (dma_mapping_error(&dev->dev, phys)) {
687#ifdef __ARMEB__
688 dev_kfree_skb(skb); 862 dev_kfree_skb(skb);
689#else 863#ifndef __ARMEB__
690 kfree(mem); 864 kfree(mem);
691#endif 865#endif
692 dev->stats.tx_dropped++; 866 dev->stats.tx_dropped++;
@@ -728,6 +902,13 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
728#if DEBUG_TX 902#if DEBUG_TX
729 printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name); 903 printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name);
730#endif 904#endif
905
906 ixp_tx_timestamp(port, skb);
907 skb_tx_timestamp(skb);
908
909#ifndef __ARMEB__
910 dev_kfree_skb(skb);
911#endif
731 return NETDEV_TX_OK; 912 return NETDEV_TX_OK;
732} 913}
733 914
@@ -783,6 +964,9 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
783 if (!netif_running(dev)) 964 if (!netif_running(dev))
784 return -EINVAL; 965 return -EINVAL;
785 966
967 if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP)
968 return hwtstamp_ioctl(dev, req, cmd);
969
786 return phy_mii_ioctl(port->phydev, req, cmd); 970 return phy_mii_ioctl(port->phydev, req, cmd);
787} 971}
788 972
@@ -1171,6 +1355,11 @@ static int __devinit eth_init_one(struct platform_device *pdev)
1171 char phy_id[MII_BUS_ID_SIZE + 3]; 1355 char phy_id[MII_BUS_ID_SIZE + 3];
1172 int err; 1356 int err;
1173 1357
1358 if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
1359 pr_err("ixp4xx_eth: bad ptp filter\n");
1360 return -EINVAL;
1361 }
1362
1174 if (!(dev = alloc_etherdev(sizeof(struct port)))) 1363 if (!(dev = alloc_etherdev(sizeof(struct port))))
1175 return -ENOMEM; 1364 return -ENOMEM;
1176 1365
diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c
new file mode 100644
index 000000000000..d8e175382d1d
--- /dev/null
+++ b/drivers/net/gianfar_ptp.c
@@ -0,0 +1,588 @@
1/*
2 * PTP 1588 clock using the eTSEC
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/device.h>
21#include <linux/hrtimer.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/of.h>
27#include <linux/of_platform.h>
28#include <linux/timex.h>
29#include <linux/io.h>
30
31#include <linux/ptp_clock_kernel.h>
32
33#include "gianfar.h"
34
35/*
36 * gianfar ptp registers
37 * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
38 */
39struct gianfar_ptp_registers {
40 u32 tmr_ctrl; /* Timer control register */
41 u32 tmr_tevent; /* Timestamp event register */
42 u32 tmr_temask; /* Timer event mask register */
43 u32 tmr_pevent; /* Timestamp event register */
44 u32 tmr_pemask; /* Timer event mask register */
45 u32 tmr_stat; /* Timestamp status register */
46 u32 tmr_cnt_h; /* Timer counter high register */
47 u32 tmr_cnt_l; /* Timer counter low register */
48 u32 tmr_add; /* Timer drift compensation addend register */
49 u32 tmr_acc; /* Timer accumulator register */
50 u32 tmr_prsc; /* Timer prescale */
51 u8 res1[4];
52 u32 tmroff_h; /* Timer offset high */
53 u32 tmroff_l; /* Timer offset low */
54 u8 res2[8];
55 u32 tmr_alarm1_h; /* Timer alarm 1 high register */
56 u32 tmr_alarm1_l; /* Timer alarm 1 high register */
57 u32 tmr_alarm2_h; /* Timer alarm 2 high register */
58 u32 tmr_alarm2_l; /* Timer alarm 2 high register */
59 u8 res3[48];
60 u32 tmr_fiper1; /* Timer fixed period interval */
61 u32 tmr_fiper2; /* Timer fixed period interval */
62 u32 tmr_fiper3; /* Timer fixed period interval */
63 u8 res4[20];
64 u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */
65 u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */
66 u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */
67 u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */
68};
69
70/* Bit definitions for the TMR_CTRL register */
71#define ALM1P (1<<31) /* Alarm1 output polarity */
72#define ALM2P (1<<30) /* Alarm2 output polarity */
73#define FS (1<<28) /* FIPER start indication */
74#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */
75#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */
76#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */
77#define TCLK_PERIOD_MASK (0x3ff)
78#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */
79#define FRD (1<<14) /* FIPER Realignment Disable */
80#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */
81#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */
82#define ETEP2 (1<<9) /* External trigger 2 edge polarity */
83#define ETEP1 (1<<8) /* External trigger 1 edge polarity */
84#define COPH (1<<7) /* Generated clock output phase. */
85#define CIPH (1<<6) /* External oscillator input clock phase */
86#define TMSR (1<<5) /* Timer soft reset. */
87#define BYP (1<<3) /* Bypass drift compensated clock */
88#define TE (1<<2) /* 1588 timer enable. */
89#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */
90#define CKSEL_MASK (0x3)
91
92/* Bit definitions for the TMR_TEVENT register */
93#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */
94#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */
95#define ALM2 (1<<17) /* Current time = alarm time register 2 */
96#define ALM1 (1<<16) /* Current time = alarm time register 1 */
97#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */
98#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */
99#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */
100
101/* Bit definitions for the TMR_TEMASK register */
102#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */
103#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */
104#define ALM2EN (1<<17) /* Timer ALM2 event enable */
105#define ALM1EN (1<<16) /* Timer ALM1 event enable */
106#define PP1EN (1<<7) /* Periodic pulse event 1 enable */
107#define PP2EN (1<<6) /* Periodic pulse event 2 enable */
108
109/* Bit definitions for the TMR_PEVENT register */
110#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */
111#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */
112#define RXP (1<<0) /* PTP frame has been received */
113
114/* Bit definitions for the TMR_PEMASK register */
115#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */
116#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */
117#define RXPEN (1<<0) /* Receive PTP packet event enable */
118
119/* Bit definitions for the TMR_STAT register */
120#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */
121#define STAT_VEC_MASK (0x3f)
122
123/* Bit definitions for the TMR_PRSC register */
124#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */
125#define PRSC_OCK_MASK (0xffff)
126
127
128#define DRIVER "gianfar_ptp"
129#define DEFAULT_CKSEL 1
130#define N_ALARM 1 /* first alarm is used internally to reset fipers */
131#define N_EXT_TS 2
132#define REG_SIZE sizeof(struct gianfar_ptp_registers)
133
134struct etsects {
135 struct gianfar_ptp_registers *regs;
136 spinlock_t lock; /* protects regs */
137 struct ptp_clock *clock;
138 struct ptp_clock_info caps;
139 struct resource *rsrc;
140 int irq;
141 u64 alarm_interval; /* for periodic alarm */
142 u64 alarm_value;
143 u32 tclk_period; /* nanoseconds */
144 u32 tmr_prsc;
145 u32 tmr_add;
146 u32 cksel;
147 u32 tmr_fiper1;
148 u32 tmr_fiper2;
149};
150
151/*
152 * Register access functions
153 */
154
155/* Caller must hold etsects->lock. */
156static u64 tmr_cnt_read(struct etsects *etsects)
157{
158 u64 ns;
159 u32 lo, hi;
160
161 lo = gfar_read(&etsects->regs->tmr_cnt_l);
162 hi = gfar_read(&etsects->regs->tmr_cnt_h);
163 ns = ((u64) hi) << 32;
164 ns |= lo;
165 return ns;
166}
167
168/* Caller must hold etsects->lock. */
169static void tmr_cnt_write(struct etsects *etsects, u64 ns)
170{
171 u32 hi = ns >> 32;
172 u32 lo = ns & 0xffffffff;
173
174 gfar_write(&etsects->regs->tmr_cnt_l, lo);
175 gfar_write(&etsects->regs->tmr_cnt_h, hi);
176}
177
178/* Caller must hold etsects->lock. */
179static void set_alarm(struct etsects *etsects)
180{
181 u64 ns;
182 u32 lo, hi;
183
184 ns = tmr_cnt_read(etsects) + 1500000000ULL;
185 ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
186 ns -= etsects->tclk_period;
187 hi = ns >> 32;
188 lo = ns & 0xffffffff;
189 gfar_write(&etsects->regs->tmr_alarm1_l, lo);
190 gfar_write(&etsects->regs->tmr_alarm1_h, hi);
191}
192
193/* Caller must hold etsects->lock. */
194static void set_fipers(struct etsects *etsects)
195{
196 u32 tmr_ctrl = gfar_read(&etsects->regs->tmr_ctrl);
197
198 gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl & (~TE));
199 gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc);
200 gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
201 gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
202 set_alarm(etsects);
203 gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|TE);
204}
205
206/*
207 * Interrupt service routine
208 */
209
210static irqreturn_t isr(int irq, void *priv)
211{
212 struct etsects *etsects = priv;
213 struct ptp_clock_event event;
214 u64 ns;
215 u32 ack = 0, lo, hi, mask, val;
216
217 val = gfar_read(&etsects->regs->tmr_tevent);
218
219 if (val & ETS1) {
220 ack |= ETS1;
221 hi = gfar_read(&etsects->regs->tmr_etts1_h);
222 lo = gfar_read(&etsects->regs->tmr_etts1_l);
223 event.type = PTP_CLOCK_EXTTS;
224 event.index = 0;
225 event.timestamp = ((u64) hi) << 32;
226 event.timestamp |= lo;
227 ptp_clock_event(etsects->clock, &event);
228 }
229
230 if (val & ETS2) {
231 ack |= ETS2;
232 hi = gfar_read(&etsects->regs->tmr_etts2_h);
233 lo = gfar_read(&etsects->regs->tmr_etts2_l);
234 event.type = PTP_CLOCK_EXTTS;
235 event.index = 1;
236 event.timestamp = ((u64) hi) << 32;
237 event.timestamp |= lo;
238 ptp_clock_event(etsects->clock, &event);
239 }
240
241 if (val & ALM2) {
242 ack |= ALM2;
243 if (etsects->alarm_value) {
244 event.type = PTP_CLOCK_ALARM;
245 event.index = 0;
246 event.timestamp = etsects->alarm_value;
247 ptp_clock_event(etsects->clock, &event);
248 }
249 if (etsects->alarm_interval) {
250 ns = etsects->alarm_value + etsects->alarm_interval;
251 hi = ns >> 32;
252 lo = ns & 0xffffffff;
253 spin_lock(&etsects->lock);
254 gfar_write(&etsects->regs->tmr_alarm2_l, lo);
255 gfar_write(&etsects->regs->tmr_alarm2_h, hi);
256 spin_unlock(&etsects->lock);
257 etsects->alarm_value = ns;
258 } else {
259 gfar_write(&etsects->regs->tmr_tevent, ALM2);
260 spin_lock(&etsects->lock);
261 mask = gfar_read(&etsects->regs->tmr_temask);
262 mask &= ~ALM2EN;
263 gfar_write(&etsects->regs->tmr_temask, mask);
264 spin_unlock(&etsects->lock);
265 etsects->alarm_value = 0;
266 etsects->alarm_interval = 0;
267 }
268 }
269
270 if (val & PP1) {
271 ack |= PP1;
272 event.type = PTP_CLOCK_PPS;
273 ptp_clock_event(etsects->clock, &event);
274 }
275
276 if (ack) {
277 gfar_write(&etsects->regs->tmr_tevent, ack);
278 return IRQ_HANDLED;
279 } else
280 return IRQ_NONE;
281}
282
283/*
284 * PTP clock operations
285 */
286
287static int ptp_gianfar_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
288{
289 u64 adj;
290 u32 diff, tmr_add;
291 int neg_adj = 0;
292 struct etsects *etsects = container_of(ptp, struct etsects, caps);
293
294 if (ppb < 0) {
295 neg_adj = 1;
296 ppb = -ppb;
297 }
298 tmr_add = etsects->tmr_add;
299 adj = tmr_add;
300 adj *= ppb;
301 diff = div_u64(adj, 1000000000ULL);
302
303 tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
304
305 gfar_write(&etsects->regs->tmr_add, tmr_add);
306
307 return 0;
308}
309
310static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta)
311{
312 s64 now;
313 unsigned long flags;
314 struct etsects *etsects = container_of(ptp, struct etsects, caps);
315
316 spin_lock_irqsave(&etsects->lock, flags);
317
318 now = tmr_cnt_read(etsects);
319 now += delta;
320 tmr_cnt_write(etsects, now);
321
322 spin_unlock_irqrestore(&etsects->lock, flags);
323
324 set_fipers(etsects);
325
326 return 0;
327}
328
329static int ptp_gianfar_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
330{
331 u64 ns;
332 u32 remainder;
333 unsigned long flags;
334 struct etsects *etsects = container_of(ptp, struct etsects, caps);
335
336 spin_lock_irqsave(&etsects->lock, flags);
337
338 ns = tmr_cnt_read(etsects);
339
340 spin_unlock_irqrestore(&etsects->lock, flags);
341
342 ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
343 ts->tv_nsec = remainder;
344 return 0;
345}
346
347static int ptp_gianfar_settime(struct ptp_clock_info *ptp,
348 const struct timespec *ts)
349{
350 u64 ns;
351 unsigned long flags;
352 struct etsects *etsects = container_of(ptp, struct etsects, caps);
353
354 ns = ts->tv_sec * 1000000000ULL;
355 ns += ts->tv_nsec;
356
357 spin_lock_irqsave(&etsects->lock, flags);
358
359 tmr_cnt_write(etsects, ns);
360 set_fipers(etsects);
361
362 spin_unlock_irqrestore(&etsects->lock, flags);
363
364 return 0;
365}
366
367static int ptp_gianfar_enable(struct ptp_clock_info *ptp,
368 struct ptp_clock_request *rq, int on)
369{
370 struct etsects *etsects = container_of(ptp, struct etsects, caps);
371 unsigned long flags;
372 u32 bit, mask;
373
374 switch (rq->type) {
375 case PTP_CLK_REQ_EXTTS:
376 switch (rq->extts.index) {
377 case 0:
378 bit = ETS1EN;
379 break;
380 case 1:
381 bit = ETS2EN;
382 break;
383 default:
384 return -EINVAL;
385 }
386 spin_lock_irqsave(&etsects->lock, flags);
387 mask = gfar_read(&etsects->regs->tmr_temask);
388 if (on)
389 mask |= bit;
390 else
391 mask &= ~bit;
392 gfar_write(&etsects->regs->tmr_temask, mask);
393 spin_unlock_irqrestore(&etsects->lock, flags);
394 return 0;
395
396 case PTP_CLK_REQ_PPS:
397 spin_lock_irqsave(&etsects->lock, flags);
398 mask = gfar_read(&etsects->regs->tmr_temask);
399 if (on)
400 mask |= PP1EN;
401 else
402 mask &= ~PP1EN;
403 gfar_write(&etsects->regs->tmr_temask, mask);
404 spin_unlock_irqrestore(&etsects->lock, flags);
405 return 0;
406
407 default:
408 break;
409 }
410
411 return -EOPNOTSUPP;
412}
413
414static struct ptp_clock_info ptp_gianfar_caps = {
415 .owner = THIS_MODULE,
416 .name = "gianfar clock",
417 .max_adj = 512000,
418 .n_alarm = N_ALARM,
419 .n_ext_ts = N_EXT_TS,
420 .n_per_out = 0,
421 .pps = 1,
422 .adjfreq = ptp_gianfar_adjfreq,
423 .adjtime = ptp_gianfar_adjtime,
424 .gettime = ptp_gianfar_gettime,
425 .settime = ptp_gianfar_settime,
426 .enable = ptp_gianfar_enable,
427};
428
429/* OF device tree */
430
431static int get_of_u32(struct device_node *node, char *str, u32 *val)
432{
433 int plen;
434 const u32 *prop = of_get_property(node, str, &plen);
435
436 if (!prop || plen != sizeof(*prop))
437 return -1;
438 *val = *prop;
439 return 0;
440}
441
442static int gianfar_ptp_probe(struct platform_device *dev)
443{
444 struct device_node *node = dev->dev.of_node;
445 struct etsects *etsects;
446 struct timespec now;
447 int err = -ENOMEM;
448 u32 tmr_ctrl;
449 unsigned long flags;
450
451 etsects = kzalloc(sizeof(*etsects), GFP_KERNEL);
452 if (!etsects)
453 goto no_memory;
454
455 err = -ENODEV;
456
457 etsects->caps = ptp_gianfar_caps;
458 etsects->cksel = DEFAULT_CKSEL;
459
460 if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) ||
461 get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) ||
462 get_of_u32(node, "fsl,tmr-add", &etsects->tmr_add) ||
463 get_of_u32(node, "fsl,tmr-fiper1", &etsects->tmr_fiper1) ||
464 get_of_u32(node, "fsl,tmr-fiper2", &etsects->tmr_fiper2) ||
465 get_of_u32(node, "fsl,max-adj", &etsects->caps.max_adj)) {
466 pr_err("device tree node missing required elements\n");
467 goto no_node;
468 }
469
470 etsects->irq = platform_get_irq(dev, 0);
471
472 if (etsects->irq == NO_IRQ) {
473 pr_err("irq not in device tree\n");
474 goto no_node;
475 }
476 if (request_irq(etsects->irq, isr, 0, DRIVER, etsects)) {
477 pr_err("request_irq failed\n");
478 goto no_node;
479 }
480
481 etsects->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
482 if (!etsects->rsrc) {
483 pr_err("no resource\n");
484 goto no_resource;
485 }
486 if (request_resource(&ioport_resource, etsects->rsrc)) {
487 pr_err("resource busy\n");
488 goto no_resource;
489 }
490
491 spin_lock_init(&etsects->lock);
492
493 etsects->regs = ioremap(etsects->rsrc->start,
494 1 + etsects->rsrc->end - etsects->rsrc->start);
495 if (!etsects->regs) {
496 pr_err("ioremap ptp registers failed\n");
497 goto no_ioremap;
498 }
499 getnstimeofday(&now);
500 ptp_gianfar_settime(&etsects->caps, &now);
501
502 tmr_ctrl =
503 (etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
504 (etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT;
505
506 spin_lock_irqsave(&etsects->lock, flags);
507
508 gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl);
509 gfar_write(&etsects->regs->tmr_add, etsects->tmr_add);
510 gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc);
511 gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
512 gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
513 set_alarm(etsects);
514 gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE);
515
516 spin_unlock_irqrestore(&etsects->lock, flags);
517
518 etsects->clock = ptp_clock_register(&etsects->caps);
519 if (IS_ERR(etsects->clock)) {
520 err = PTR_ERR(etsects->clock);
521 goto no_clock;
522 }
523
524 dev_set_drvdata(&dev->dev, etsects);
525
526 return 0;
527
528no_clock:
529no_ioremap:
530 release_resource(etsects->rsrc);
531no_resource:
532 free_irq(etsects->irq, etsects);
533no_node:
534 kfree(etsects);
535no_memory:
536 return err;
537}
538
539static int gianfar_ptp_remove(struct platform_device *dev)
540{
541 struct etsects *etsects = dev_get_drvdata(&dev->dev);
542
543 gfar_write(&etsects->regs->tmr_temask, 0);
544 gfar_write(&etsects->regs->tmr_ctrl, 0);
545
546 ptp_clock_unregister(etsects->clock);
547 iounmap(etsects->regs);
548 release_resource(etsects->rsrc);
549 free_irq(etsects->irq, etsects);
550 kfree(etsects);
551
552 return 0;
553}
554
555static struct of_device_id match_table[] = {
556 { .compatible = "fsl,etsec-ptp" },
557 {},
558};
559
560static struct platform_driver gianfar_ptp_driver = {
561 .driver = {
562 .name = "gianfar_ptp",
563 .of_match_table = match_table,
564 .owner = THIS_MODULE,
565 },
566 .probe = gianfar_ptp_probe,
567 .remove = gianfar_ptp_remove,
568};
569
570/* module operations */
571
572static int __init ptp_gianfar_init(void)
573{
574 return platform_driver_register(&gianfar_ptp_driver);
575}
576
577module_init(ptp_gianfar_init);
578
579static void __exit ptp_gianfar_exit(void)
580{
581 platform_driver_unregister(&gianfar_ptp_driver);
582}
583
584module_exit(ptp_gianfar_exit);
585
586MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
587MODULE_DESCRIPTION("PTP clock using the eTSEC");
588MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 13bebab65d02..2333215bbb32 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_FIXED_PHY) += fixed.o
19obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o 19obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
20obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o 20obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
21obj-$(CONFIG_NATIONAL_PHY) += national.o 21obj-$(CONFIG_NATIONAL_PHY) += national.o
22obj-$(CONFIG_DP83640_PHY) += dp83640.o
22obj-$(CONFIG_STE10XP) += ste10Xp.o 23obj-$(CONFIG_STE10XP) += ste10Xp.o
23obj-$(CONFIG_MICREL_PHY) += micrel.o 24obj-$(CONFIG_MICREL_PHY) += micrel.o
24obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o 25obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
new file mode 100644
index 000000000000..b0c9522bb535
--- /dev/null
+++ b/drivers/net/phy/dp83640.c
@@ -0,0 +1,1100 @@
1/*
2 * Driver for the National Semiconductor DP83640 PHYTER
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/ethtool.h>
21#include <linux/kernel.h>
22#include <linux/list.h>
23#include <linux/mii.h>
24#include <linux/module.h>
25#include <linux/net_tstamp.h>
26#include <linux/netdevice.h>
27#include <linux/phy.h>
28#include <linux/ptp_classify.h>
29#include <linux/ptp_clock_kernel.h>
30
31#include "dp83640_reg.h"
32
33#define DP83640_PHY_ID 0x20005ce1
34#define PAGESEL 0x13
35#define LAYER4 0x02
36#define LAYER2 0x01
37#define MAX_RXTS 4
38#define MAX_TXTS 4
39#define N_EXT_TS 1
40#define PSF_PTPVER 2
41#define PSF_EVNT 0x4000
42#define PSF_RX 0x2000
43#define PSF_TX 0x1000
44#define EXT_EVENT 1
45#define EXT_GPIO 1
46#define CAL_EVENT 2
47#define CAL_GPIO 9
48#define CAL_TRIGGER 2
49
50/* phyter seems to miss the mark by 16 ns */
51#define ADJTIME_FIX 16
52
53#if defined(__BIG_ENDIAN)
54#define ENDIAN_FLAG 0
55#elif defined(__LITTLE_ENDIAN)
56#define ENDIAN_FLAG PSF_ENDIAN
57#endif
58
59#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb))
60
61struct phy_rxts {
62 u16 ns_lo; /* ns[15:0] */
63 u16 ns_hi; /* overflow[1:0], ns[29:16] */
64 u16 sec_lo; /* sec[15:0] */
65 u16 sec_hi; /* sec[31:16] */
66 u16 seqid; /* sequenceId[15:0] */
67 u16 msgtype; /* messageType[3:0], hash[11:0] */
68};
69
70struct phy_txts {
71 u16 ns_lo; /* ns[15:0] */
72 u16 ns_hi; /* overflow[1:0], ns[29:16] */
73 u16 sec_lo; /* sec[15:0] */
74 u16 sec_hi; /* sec[31:16] */
75};
76
77struct rxts {
78 struct list_head list;
79 unsigned long tmo;
80 u64 ns;
81 u16 seqid;
82 u8 msgtype;
83 u16 hash;
84};
85
86struct dp83640_clock;
87
88struct dp83640_private {
89 struct list_head list;
90 struct dp83640_clock *clock;
91 struct phy_device *phydev;
92 struct work_struct ts_work;
93 int hwts_tx_en;
94 int hwts_rx_en;
95 int layer;
96 int version;
97 /* remember state of cfg0 during calibration */
98 int cfg0;
99 /* remember the last event time stamp */
100 struct phy_txts edata;
101 /* list of rx timestamps */
102 struct list_head rxts;
103 struct list_head rxpool;
104 struct rxts rx_pool_data[MAX_RXTS];
105 /* protects above three fields from concurrent access */
106 spinlock_t rx_lock;
107 /* queues of incoming and outgoing packets */
108 struct sk_buff_head rx_queue;
109 struct sk_buff_head tx_queue;
110};
111
112struct dp83640_clock {
113 /* keeps the instance in the 'phyter_clocks' list */
114 struct list_head list;
115 /* we create one clock instance per MII bus */
116 struct mii_bus *bus;
117 /* protects extended registers from concurrent access */
118 struct mutex extreg_lock;
119 /* remembers which page was last selected */
120 int page;
121 /* our advertised capabilities */
122 struct ptp_clock_info caps;
123 /* protects the three fields below from concurrent access */
124 struct mutex clock_lock;
125 /* the one phyter from which we shall read */
126 struct dp83640_private *chosen;
127 /* list of the other attached phyters, not chosen */
128 struct list_head phylist;
129 /* reference to our PTP hardware clock */
130 struct ptp_clock *ptp_clock;
131};
132
133/* globals */
134
135static int chosen_phy = -1;
136static ushort cal_gpio = 4;
137
138module_param(chosen_phy, int, 0444);
139module_param(cal_gpio, ushort, 0444);
140
141MODULE_PARM_DESC(chosen_phy, \
142 "The address of the PHY to use for the ancillary clock features");
143MODULE_PARM_DESC(cal_gpio, \
144 "Which GPIO line to use for synchronizing multiple PHYs");
145
146/* a list of clocks and a mutex to protect it */
147static LIST_HEAD(phyter_clocks);
148static DEFINE_MUTEX(phyter_clocks_lock);
149
150static void rx_timestamp_work(struct work_struct *work);
151
152/* extended register access functions */
153
154#define BROADCAST_ADDR 31
155
156static inline int broadcast_write(struct mii_bus *bus, u32 regnum, u16 val)
157{
158 return mdiobus_write(bus, BROADCAST_ADDR, regnum, val);
159}
160
161/* Caller must hold extreg_lock. */
162static int ext_read(struct phy_device *phydev, int page, u32 regnum)
163{
164 struct dp83640_private *dp83640 = phydev->priv;
165 int val;
166
167 if (dp83640->clock->page != page) {
168 broadcast_write(phydev->bus, PAGESEL, page);
169 dp83640->clock->page = page;
170 }
171 val = phy_read(phydev, regnum);
172
173 return val;
174}
175
176/* Caller must hold extreg_lock. */
177static void ext_write(int broadcast, struct phy_device *phydev,
178 int page, u32 regnum, u16 val)
179{
180 struct dp83640_private *dp83640 = phydev->priv;
181
182 if (dp83640->clock->page != page) {
183 broadcast_write(phydev->bus, PAGESEL, page);
184 dp83640->clock->page = page;
185 }
186 if (broadcast)
187 broadcast_write(phydev->bus, regnum, val);
188 else
189 phy_write(phydev, regnum, val);
190}
191
192/* Caller must hold extreg_lock. */
193static int tdr_write(int bc, struct phy_device *dev,
194 const struct timespec *ts, u16 cmd)
195{
196 ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec & 0xffff);/* ns[15:0] */
197 ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec >> 16); /* ns[31:16] */
198 ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec & 0xffff); /* sec[15:0] */
199 ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec >> 16); /* sec[31:16]*/
200
201 ext_write(bc, dev, PAGE4, PTP_CTL, cmd);
202
203 return 0;
204}
205
206/* convert phy timestamps into driver timestamps */
207
208static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
209{
210 u32 sec;
211
212 sec = p->sec_lo;
213 sec |= p->sec_hi << 16;
214
215 rxts->ns = p->ns_lo;
216 rxts->ns |= (p->ns_hi & 0x3fff) << 16;
217 rxts->ns += ((u64)sec) * 1000000000ULL;
218 rxts->seqid = p->seqid;
219 rxts->msgtype = (p->msgtype >> 12) & 0xf;
220 rxts->hash = p->msgtype & 0x0fff;
221 rxts->tmo = jiffies + HZ;
222}
223
224static u64 phy2txts(struct phy_txts *p)
225{
226 u64 ns;
227 u32 sec;
228
229 sec = p->sec_lo;
230 sec |= p->sec_hi << 16;
231
232 ns = p->ns_lo;
233 ns |= (p->ns_hi & 0x3fff) << 16;
234 ns += ((u64)sec) * 1000000000ULL;
235
236 return ns;
237}
238
239/* ptp clock methods */
240
241static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
242{
243 struct dp83640_clock *clock =
244 container_of(ptp, struct dp83640_clock, caps);
245 struct phy_device *phydev = clock->chosen->phydev;
246 u64 rate;
247 int neg_adj = 0;
248 u16 hi, lo;
249
250 if (ppb < 0) {
251 neg_adj = 1;
252 ppb = -ppb;
253 }
254 rate = ppb;
255 rate <<= 26;
256 rate = div_u64(rate, 1953125);
257
258 hi = (rate >> 16) & PTP_RATE_HI_MASK;
259 if (neg_adj)
260 hi |= PTP_RATE_DIR;
261
262 lo = rate & 0xffff;
263
264 mutex_lock(&clock->extreg_lock);
265
266 ext_write(1, phydev, PAGE4, PTP_RATEH, hi);
267 ext_write(1, phydev, PAGE4, PTP_RATEL, lo);
268
269 mutex_unlock(&clock->extreg_lock);
270
271 return 0;
272}
273
274static int ptp_dp83640_adjtime(struct ptp_clock_info *ptp, s64 delta)
275{
276 struct dp83640_clock *clock =
277 container_of(ptp, struct dp83640_clock, caps);
278 struct phy_device *phydev = clock->chosen->phydev;
279 struct timespec ts;
280 int err;
281
282 delta += ADJTIME_FIX;
283
284 ts = ns_to_timespec(delta);
285
286 mutex_lock(&clock->extreg_lock);
287
288 err = tdr_write(1, phydev, &ts, PTP_STEP_CLK);
289
290 mutex_unlock(&clock->extreg_lock);
291
292 return err;
293}
294
295static int ptp_dp83640_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
296{
297 struct dp83640_clock *clock =
298 container_of(ptp, struct dp83640_clock, caps);
299 struct phy_device *phydev = clock->chosen->phydev;
300 unsigned int val[4];
301
302 mutex_lock(&clock->extreg_lock);
303
304 ext_write(0, phydev, PAGE4, PTP_CTL, PTP_RD_CLK);
305
306 val[0] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[15:0] */
307 val[1] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[31:16] */
308 val[2] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[15:0] */
309 val[3] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[31:16] */
310
311 mutex_unlock(&clock->extreg_lock);
312
313 ts->tv_nsec = val[0] | (val[1] << 16);
314 ts->tv_sec = val[2] | (val[3] << 16);
315
316 return 0;
317}
318
319static int ptp_dp83640_settime(struct ptp_clock_info *ptp,
320 const struct timespec *ts)
321{
322 struct dp83640_clock *clock =
323 container_of(ptp, struct dp83640_clock, caps);
324 struct phy_device *phydev = clock->chosen->phydev;
325 int err;
326
327 mutex_lock(&clock->extreg_lock);
328
329 err = tdr_write(1, phydev, ts, PTP_LOAD_CLK);
330
331 mutex_unlock(&clock->extreg_lock);
332
333 return err;
334}
335
336static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
337 struct ptp_clock_request *rq, int on)
338{
339 struct dp83640_clock *clock =
340 container_of(ptp, struct dp83640_clock, caps);
341 struct phy_device *phydev = clock->chosen->phydev;
342 u16 evnt;
343
344 switch (rq->type) {
345 case PTP_CLK_REQ_EXTTS:
346 if (rq->extts.index != 0)
347 return -EINVAL;
348 evnt = EVNT_WR | (EXT_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
349 if (on) {
350 evnt |= (EXT_GPIO & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
351 evnt |= EVNT_RISE;
352 }
353 ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
354 return 0;
355 default:
356 break;
357 }
358
359 return -EOPNOTSUPP;
360}
361
362static u8 status_frame_dst[6] = { 0x01, 0x1B, 0x19, 0x00, 0x00, 0x00 };
363static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F };
364
365static void enable_status_frames(struct phy_device *phydev, bool on)
366{
367 u16 cfg0 = 0, ver;
368
369 if (on)
370 cfg0 = PSF_EVNT_EN | PSF_RXTS_EN | PSF_TXTS_EN | ENDIAN_FLAG;
371
372 ver = (PSF_PTPVER & VERSIONPTP_MASK) << VERSIONPTP_SHIFT;
373
374 ext_write(0, phydev, PAGE5, PSF_CFG0, cfg0);
375 ext_write(0, phydev, PAGE6, PSF_CFG1, ver);
376
377 if (!phydev->attached_dev) {
378 pr_warning("dp83640: expected to find an attached netdevice\n");
379 return;
380 }
381
382 if (on) {
383 if (dev_mc_add(phydev->attached_dev, status_frame_dst))
384 pr_warning("dp83640: failed to add mc address\n");
385 } else {
386 if (dev_mc_del(phydev->attached_dev, status_frame_dst))
387 pr_warning("dp83640: failed to delete mc address\n");
388 }
389}
390
391static bool is_status_frame(struct sk_buff *skb, int type)
392{
393 struct ethhdr *h = eth_hdr(skb);
394
395 if (PTP_CLASS_V2_L2 == type &&
396 !memcmp(h->h_source, status_frame_src, sizeof(status_frame_src)))
397 return true;
398 else
399 return false;
400}
401
402static int expired(struct rxts *rxts)
403{
404 return time_after(jiffies, rxts->tmo);
405}
406
407/* Caller must hold rx_lock. */
408static void prune_rx_ts(struct dp83640_private *dp83640)
409{
410 struct list_head *this, *next;
411 struct rxts *rxts;
412
413 list_for_each_safe(this, next, &dp83640->rxts) {
414 rxts = list_entry(this, struct rxts, list);
415 if (expired(rxts)) {
416 list_del_init(&rxts->list);
417 list_add(&rxts->list, &dp83640->rxpool);
418 }
419 }
420}
421
422/* synchronize the phyters so they act as one clock */
423
424static void enable_broadcast(struct phy_device *phydev, int init_page, int on)
425{
426 int val;
427 phy_write(phydev, PAGESEL, 0);
428 val = phy_read(phydev, PHYCR2);
429 if (on)
430 val |= BC_WRITE;
431 else
432 val &= ~BC_WRITE;
433 phy_write(phydev, PHYCR2, val);
434 phy_write(phydev, PAGESEL, init_page);
435}
436
437static void recalibrate(struct dp83640_clock *clock)
438{
439 s64 now, diff;
440 struct phy_txts event_ts;
441 struct timespec ts;
442 struct list_head *this;
443 struct dp83640_private *tmp;
444 struct phy_device *master = clock->chosen->phydev;
445 u16 cfg0, evnt, ptp_trig, trigger, val;
446
447 trigger = CAL_TRIGGER;
448
449 mutex_lock(&clock->extreg_lock);
450
451 /*
452 * enable broadcast, disable status frames, enable ptp clock
453 */
454 list_for_each(this, &clock->phylist) {
455 tmp = list_entry(this, struct dp83640_private, list);
456 enable_broadcast(tmp->phydev, clock->page, 1);
457 tmp->cfg0 = ext_read(tmp->phydev, PAGE5, PSF_CFG0);
458 ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, 0);
459 ext_write(0, tmp->phydev, PAGE4, PTP_CTL, PTP_ENABLE);
460 }
461 enable_broadcast(master, clock->page, 1);
462 cfg0 = ext_read(master, PAGE5, PSF_CFG0);
463 ext_write(0, master, PAGE5, PSF_CFG0, 0);
464 ext_write(0, master, PAGE4, PTP_CTL, PTP_ENABLE);
465
466 /*
467 * enable an event timestamp
468 */
469 evnt = EVNT_WR | EVNT_RISE | EVNT_SINGLE;
470 evnt |= (CAL_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
471 evnt |= (cal_gpio & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
472
473 list_for_each(this, &clock->phylist) {
474 tmp = list_entry(this, struct dp83640_private, list);
475 ext_write(0, tmp->phydev, PAGE5, PTP_EVNT, evnt);
476 }
477 ext_write(0, master, PAGE5, PTP_EVNT, evnt);
478
479 /*
480 * configure a trigger
481 */
482 ptp_trig = TRIG_WR | TRIG_IF_LATE | TRIG_PULSE;
483 ptp_trig |= (trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT;
484 ptp_trig |= (cal_gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT;
485 ext_write(0, master, PAGE5, PTP_TRIG, ptp_trig);
486
487 /* load trigger */
488 val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
489 val |= TRIG_LOAD;
490 ext_write(0, master, PAGE4, PTP_CTL, val);
491
492 /* enable trigger */
493 val &= ~TRIG_LOAD;
494 val |= TRIG_EN;
495 ext_write(0, master, PAGE4, PTP_CTL, val);
496
497 /* disable trigger */
498 val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
499 val |= TRIG_DIS;
500 ext_write(0, master, PAGE4, PTP_CTL, val);
501
502 /*
503 * read out and correct offsets
504 */
505 val = ext_read(master, PAGE4, PTP_STS);
506 pr_info("master PTP_STS 0x%04hx", val);
507 val = ext_read(master, PAGE4, PTP_ESTS);
508 pr_info("master PTP_ESTS 0x%04hx", val);
509 event_ts.ns_lo = ext_read(master, PAGE4, PTP_EDATA);
510 event_ts.ns_hi = ext_read(master, PAGE4, PTP_EDATA);
511 event_ts.sec_lo = ext_read(master, PAGE4, PTP_EDATA);
512 event_ts.sec_hi = ext_read(master, PAGE4, PTP_EDATA);
513 now = phy2txts(&event_ts);
514
515 list_for_each(this, &clock->phylist) {
516 tmp = list_entry(this, struct dp83640_private, list);
517 val = ext_read(tmp->phydev, PAGE4, PTP_STS);
518 pr_info("slave PTP_STS 0x%04hx", val);
519 val = ext_read(tmp->phydev, PAGE4, PTP_ESTS);
520 pr_info("slave PTP_ESTS 0x%04hx", val);
521 event_ts.ns_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
522 event_ts.ns_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
523 event_ts.sec_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
524 event_ts.sec_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
525 diff = now - (s64) phy2txts(&event_ts);
526 pr_info("slave offset %lld nanoseconds\n", diff);
527 diff += ADJTIME_FIX;
528 ts = ns_to_timespec(diff);
529 tdr_write(0, tmp->phydev, &ts, PTP_STEP_CLK);
530 }
531
532 /*
533 * restore status frames
534 */
535 list_for_each(this, &clock->phylist) {
536 tmp = list_entry(this, struct dp83640_private, list);
537 ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, tmp->cfg0);
538 }
539 ext_write(0, master, PAGE5, PSF_CFG0, cfg0);
540
541 mutex_unlock(&clock->extreg_lock);
542}
543
544/* time stamping methods */
545
546static void decode_evnt(struct dp83640_private *dp83640,
547 struct phy_txts *phy_txts, u16 ests)
548{
549 struct ptp_clock_event event;
550 int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
551
552 switch (words) { /* fall through in every case */
553 case 3:
554 dp83640->edata.sec_hi = phy_txts->sec_hi;
555 case 2:
556 dp83640->edata.sec_lo = phy_txts->sec_lo;
557 case 1:
558 dp83640->edata.ns_hi = phy_txts->ns_hi;
559 case 0:
560 dp83640->edata.ns_lo = phy_txts->ns_lo;
561 }
562
563 event.type = PTP_CLOCK_EXTTS;
564 event.index = 0;
565 event.timestamp = phy2txts(&dp83640->edata);
566
567 ptp_clock_event(dp83640->clock->ptp_clock, &event);
568}
569
570static void decode_rxts(struct dp83640_private *dp83640,
571 struct phy_rxts *phy_rxts)
572{
573 struct rxts *rxts;
574 unsigned long flags;
575
576 spin_lock_irqsave(&dp83640->rx_lock, flags);
577
578 prune_rx_ts(dp83640);
579
580 if (list_empty(&dp83640->rxpool)) {
581 pr_warning("dp83640: rx timestamp pool is empty\n");
582 goto out;
583 }
584 rxts = list_first_entry(&dp83640->rxpool, struct rxts, list);
585 list_del_init(&rxts->list);
586 phy2rxts(phy_rxts, rxts);
587 list_add_tail(&rxts->list, &dp83640->rxts);
588out:
589 spin_unlock_irqrestore(&dp83640->rx_lock, flags);
590}
591
592static void decode_txts(struct dp83640_private *dp83640,
593 struct phy_txts *phy_txts)
594{
595 struct skb_shared_hwtstamps shhwtstamps;
596 struct sk_buff *skb;
597 u64 ns;
598
599 /* We must already have the skb that triggered this. */
600
601 skb = skb_dequeue(&dp83640->tx_queue);
602
603 if (!skb) {
604 pr_warning("dp83640: have timestamp but tx_queue empty\n");
605 return;
606 }
607 ns = phy2txts(phy_txts);
608 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
609 shhwtstamps.hwtstamp = ns_to_ktime(ns);
610 skb_complete_tx_timestamp(skb, &shhwtstamps);
611}
612
613static void decode_status_frame(struct dp83640_private *dp83640,
614 struct sk_buff *skb)
615{
616 struct phy_rxts *phy_rxts;
617 struct phy_txts *phy_txts;
618 u8 *ptr;
619 int len, size;
620 u16 ests, type;
621
622 ptr = skb->data + 2;
623
624 for (len = skb_headlen(skb) - 2; len > sizeof(type); len -= size) {
625
626 type = *(u16 *)ptr;
627 ests = type & 0x0fff;
628 type = type & 0xf000;
629 len -= sizeof(type);
630 ptr += sizeof(type);
631
632 if (PSF_RX == type && len >= sizeof(*phy_rxts)) {
633
634 phy_rxts = (struct phy_rxts *) ptr;
635 decode_rxts(dp83640, phy_rxts);
636 size = sizeof(*phy_rxts);
637
638 } else if (PSF_TX == type && len >= sizeof(*phy_txts)) {
639
640 phy_txts = (struct phy_txts *) ptr;
641 decode_txts(dp83640, phy_txts);
642 size = sizeof(*phy_txts);
643
644 } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) {
645
646 phy_txts = (struct phy_txts *) ptr;
647 decode_evnt(dp83640, phy_txts, ests);
648 size = sizeof(*phy_txts);
649
650 } else {
651 size = 0;
652 break;
653 }
654 ptr += size;
655 }
656}
657
658static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
659{
660 u16 *seqid;
661 unsigned int offset;
662 u8 *msgtype, *data = skb_mac_header(skb);
663
664 /* check sequenceID, messageType, 12 bit hash of offset 20-29 */
665
666 switch (type) {
667 case PTP_CLASS_V1_IPV4:
668 case PTP_CLASS_V2_IPV4:
669 offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
670 break;
671 case PTP_CLASS_V1_IPV6:
672 case PTP_CLASS_V2_IPV6:
673 offset = OFF_PTP6;
674 break;
675 case PTP_CLASS_V2_L2:
676 offset = ETH_HLEN;
677 break;
678 case PTP_CLASS_V2_VLAN:
679 offset = ETH_HLEN + VLAN_HLEN;
680 break;
681 default:
682 return 0;
683 }
684
685 if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
686 return 0;
687
688 if (unlikely(type & PTP_CLASS_V1))
689 msgtype = data + offset + OFF_PTP_CONTROL;
690 else
691 msgtype = data + offset;
692
693 seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
694
695 return (rxts->msgtype == (*msgtype & 0xf) &&
696 rxts->seqid == ntohs(*seqid));
697}
698
699static void dp83640_free_clocks(void)
700{
701 struct dp83640_clock *clock;
702 struct list_head *this, *next;
703
704 mutex_lock(&phyter_clocks_lock);
705
706 list_for_each_safe(this, next, &phyter_clocks) {
707 clock = list_entry(this, struct dp83640_clock, list);
708 if (!list_empty(&clock->phylist)) {
709 pr_warning("phy list non-empty while unloading");
710 BUG();
711 }
712 list_del(&clock->list);
713 mutex_destroy(&clock->extreg_lock);
714 mutex_destroy(&clock->clock_lock);
715 put_device(&clock->bus->dev);
716 kfree(clock);
717 }
718
719 mutex_unlock(&phyter_clocks_lock);
720}
721
722static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
723{
724 INIT_LIST_HEAD(&clock->list);
725 clock->bus = bus;
726 mutex_init(&clock->extreg_lock);
727 mutex_init(&clock->clock_lock);
728 INIT_LIST_HEAD(&clock->phylist);
729 clock->caps.owner = THIS_MODULE;
730 sprintf(clock->caps.name, "dp83640 timer");
731 clock->caps.max_adj = 1953124;
732 clock->caps.n_alarm = 0;
733 clock->caps.n_ext_ts = N_EXT_TS;
734 clock->caps.n_per_out = 0;
735 clock->caps.pps = 0;
736 clock->caps.adjfreq = ptp_dp83640_adjfreq;
737 clock->caps.adjtime = ptp_dp83640_adjtime;
738 clock->caps.gettime = ptp_dp83640_gettime;
739 clock->caps.settime = ptp_dp83640_settime;
740 clock->caps.enable = ptp_dp83640_enable;
741 /*
742 * Get a reference to this bus instance.
743 */
744 get_device(&bus->dev);
745}
746
747static int choose_this_phy(struct dp83640_clock *clock,
748 struct phy_device *phydev)
749{
750 if (chosen_phy == -1 && !clock->chosen)
751 return 1;
752
753 if (chosen_phy == phydev->addr)
754 return 1;
755
756 return 0;
757}
758
759static struct dp83640_clock *dp83640_clock_get(struct dp83640_clock *clock)
760{
761 if (clock)
762 mutex_lock(&clock->clock_lock);
763 return clock;
764}
765
766/*
767 * Look up and lock a clock by bus instance.
768 * If there is no clock for this bus, then create it first.
769 */
770static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus)
771{
772 struct dp83640_clock *clock = NULL, *tmp;
773 struct list_head *this;
774
775 mutex_lock(&phyter_clocks_lock);
776
777 list_for_each(this, &phyter_clocks) {
778 tmp = list_entry(this, struct dp83640_clock, list);
779 if (tmp->bus == bus) {
780 clock = tmp;
781 break;
782 }
783 }
784 if (clock)
785 goto out;
786
787 clock = kzalloc(sizeof(struct dp83640_clock), GFP_KERNEL);
788 if (!clock)
789 goto out;
790
791 dp83640_clock_init(clock, bus);
792 list_add_tail(&phyter_clocks, &clock->list);
793out:
794 mutex_unlock(&phyter_clocks_lock);
795
796 return dp83640_clock_get(clock);
797}
798
799static void dp83640_clock_put(struct dp83640_clock *clock)
800{
801 mutex_unlock(&clock->clock_lock);
802}
803
804static int dp83640_probe(struct phy_device *phydev)
805{
806 struct dp83640_clock *clock;
807 struct dp83640_private *dp83640;
808 int err = -ENOMEM, i;
809
810 if (phydev->addr == BROADCAST_ADDR)
811 return 0;
812
813 clock = dp83640_clock_get_bus(phydev->bus);
814 if (!clock)
815 goto no_clock;
816
817 dp83640 = kzalloc(sizeof(struct dp83640_private), GFP_KERNEL);
818 if (!dp83640)
819 goto no_memory;
820
821 dp83640->phydev = phydev;
822 INIT_WORK(&dp83640->ts_work, rx_timestamp_work);
823
824 INIT_LIST_HEAD(&dp83640->rxts);
825 INIT_LIST_HEAD(&dp83640->rxpool);
826 for (i = 0; i < MAX_RXTS; i++)
827 list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool);
828
829 phydev->priv = dp83640;
830
831 spin_lock_init(&dp83640->rx_lock);
832 skb_queue_head_init(&dp83640->rx_queue);
833 skb_queue_head_init(&dp83640->tx_queue);
834
835 dp83640->clock = clock;
836
837 if (choose_this_phy(clock, phydev)) {
838 clock->chosen = dp83640;
839 clock->ptp_clock = ptp_clock_register(&clock->caps);
840 if (IS_ERR(clock->ptp_clock)) {
841 err = PTR_ERR(clock->ptp_clock);
842 goto no_register;
843 }
844 } else
845 list_add_tail(&dp83640->list, &clock->phylist);
846
847 if (clock->chosen && !list_empty(&clock->phylist))
848 recalibrate(clock);
849 else
850 enable_broadcast(dp83640->phydev, clock->page, 1);
851
852 dp83640_clock_put(clock);
853 return 0;
854
855no_register:
856 clock->chosen = NULL;
857 kfree(dp83640);
858no_memory:
859 dp83640_clock_put(clock);
860no_clock:
861 return err;
862}
863
864static void dp83640_remove(struct phy_device *phydev)
865{
866 struct dp83640_clock *clock;
867 struct list_head *this, *next;
868 struct dp83640_private *tmp, *dp83640 = phydev->priv;
869
870 if (phydev->addr == BROADCAST_ADDR)
871 return;
872
873 enable_status_frames(phydev, false);
874 cancel_work_sync(&dp83640->ts_work);
875
876 clock = dp83640_clock_get(dp83640->clock);
877
878 if (dp83640 == clock->chosen) {
879 ptp_clock_unregister(clock->ptp_clock);
880 clock->chosen = NULL;
881 } else {
882 list_for_each_safe(this, next, &clock->phylist) {
883 tmp = list_entry(this, struct dp83640_private, list);
884 if (tmp == dp83640) {
885 list_del_init(&tmp->list);
886 break;
887 }
888 }
889 }
890
891 dp83640_clock_put(clock);
892 kfree(dp83640);
893}
894
895static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
896{
897 struct dp83640_private *dp83640 = phydev->priv;
898 struct hwtstamp_config cfg;
899 u16 txcfg0, rxcfg0;
900
901 if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
902 return -EFAULT;
903
904 if (cfg.flags) /* reserved for future extensions */
905 return -EINVAL;
906
907 switch (cfg.tx_type) {
908 case HWTSTAMP_TX_OFF:
909 dp83640->hwts_tx_en = 0;
910 break;
911 case HWTSTAMP_TX_ON:
912 dp83640->hwts_tx_en = 1;
913 break;
914 default:
915 return -ERANGE;
916 }
917
918 switch (cfg.rx_filter) {
919 case HWTSTAMP_FILTER_NONE:
920 dp83640->hwts_rx_en = 0;
921 dp83640->layer = 0;
922 dp83640->version = 0;
923 break;
924 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
925 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
926 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
927 dp83640->hwts_rx_en = 1;
928 dp83640->layer = LAYER4;
929 dp83640->version = 1;
930 break;
931 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
932 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
933 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
934 dp83640->hwts_rx_en = 1;
935 dp83640->layer = LAYER4;
936 dp83640->version = 2;
937 break;
938 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
939 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
940 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
941 dp83640->hwts_rx_en = 1;
942 dp83640->layer = LAYER2;
943 dp83640->version = 2;
944 break;
945 case HWTSTAMP_FILTER_PTP_V2_EVENT:
946 case HWTSTAMP_FILTER_PTP_V2_SYNC:
947 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
948 dp83640->hwts_rx_en = 1;
949 dp83640->layer = LAYER4|LAYER2;
950 dp83640->version = 2;
951 break;
952 default:
953 return -ERANGE;
954 }
955
956 txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
957 rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
958
959 if (dp83640->layer & LAYER2) {
960 txcfg0 |= TX_L2_EN;
961 rxcfg0 |= RX_L2_EN;
962 }
963 if (dp83640->layer & LAYER4) {
964 txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
965 rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
966 }
967
968 if (dp83640->hwts_tx_en)
969 txcfg0 |= TX_TS_EN;
970
971 if (dp83640->hwts_rx_en)
972 rxcfg0 |= RX_TS_EN;
973
974 mutex_lock(&dp83640->clock->extreg_lock);
975
976 if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) {
977 enable_status_frames(phydev, true);
978 ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
979 }
980
981 ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0);
982 ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0);
983
984 mutex_unlock(&dp83640->clock->extreg_lock);
985
986 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
987}
988
989static void rx_timestamp_work(struct work_struct *work)
990{
991 struct dp83640_private *dp83640 =
992 container_of(work, struct dp83640_private, ts_work);
993 struct list_head *this, *next;
994 struct rxts *rxts;
995 struct skb_shared_hwtstamps *shhwtstamps;
996 struct sk_buff *skb;
997 unsigned int type;
998 unsigned long flags;
999
1000 /* Deliver each deferred packet, with or without a time stamp. */
1001
1002 while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL) {
1003 type = SKB_PTP_TYPE(skb);
1004 spin_lock_irqsave(&dp83640->rx_lock, flags);
1005 list_for_each_safe(this, next, &dp83640->rxts) {
1006 rxts = list_entry(this, struct rxts, list);
1007 if (match(skb, type, rxts)) {
1008 shhwtstamps = skb_hwtstamps(skb);
1009 memset(shhwtstamps, 0, sizeof(*shhwtstamps));
1010 shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
1011 list_del_init(&rxts->list);
1012 list_add(&rxts->list, &dp83640->rxpool);
1013 break;
1014 }
1015 }
1016 spin_unlock_irqrestore(&dp83640->rx_lock, flags);
1017 netif_rx(skb);
1018 }
1019
1020 /* Clear out expired time stamps. */
1021
1022 spin_lock_irqsave(&dp83640->rx_lock, flags);
1023 prune_rx_ts(dp83640);
1024 spin_unlock_irqrestore(&dp83640->rx_lock, flags);
1025}
1026
1027static bool dp83640_rxtstamp(struct phy_device *phydev,
1028 struct sk_buff *skb, int type)
1029{
1030 struct dp83640_private *dp83640 = phydev->priv;
1031
1032 if (!dp83640->hwts_rx_en)
1033 return false;
1034
1035 if (is_status_frame(skb, type)) {
1036 decode_status_frame(dp83640, skb);
1037 /* Let the stack drop this frame. */
1038 return false;
1039 }
1040
1041 SKB_PTP_TYPE(skb) = type;
1042 skb_queue_tail(&dp83640->rx_queue, skb);
1043 schedule_work(&dp83640->ts_work);
1044
1045 return true;
1046}
1047
1048static void dp83640_txtstamp(struct phy_device *phydev,
1049 struct sk_buff *skb, int type)
1050{
1051 struct dp83640_private *dp83640 = phydev->priv;
1052
1053 if (!dp83640->hwts_tx_en) {
1054 kfree_skb(skb);
1055 return;
1056 }
1057 skb_queue_tail(&dp83640->tx_queue, skb);
1058 schedule_work(&dp83640->ts_work);
1059}
1060
1061static struct phy_driver dp83640_driver = {
1062 .phy_id = DP83640_PHY_ID,
1063 .phy_id_mask = 0xfffffff0,
1064 .name = "NatSemi DP83640",
1065 .features = PHY_BASIC_FEATURES,
1066 .flags = 0,
1067 .probe = dp83640_probe,
1068 .remove = dp83640_remove,
1069 .config_aneg = genphy_config_aneg,
1070 .read_status = genphy_read_status,
1071 .hwtstamp = dp83640_hwtstamp,
1072 .rxtstamp = dp83640_rxtstamp,
1073 .txtstamp = dp83640_txtstamp,
1074 .driver = {.owner = THIS_MODULE,}
1075};
1076
1077static int __init dp83640_init(void)
1078{
1079 return phy_driver_register(&dp83640_driver);
1080}
1081
1082static void __exit dp83640_exit(void)
1083{
1084 dp83640_free_clocks();
1085 phy_driver_unregister(&dp83640_driver);
1086}
1087
1088MODULE_DESCRIPTION("National Semiconductor DP83640 PHY driver");
1089MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
1090MODULE_LICENSE("GPL");
1091
1092module_init(dp83640_init);
1093module_exit(dp83640_exit);
1094
1095static struct mdio_device_id __maybe_unused dp83640_tbl[] = {
1096 { DP83640_PHY_ID, 0xfffffff0 },
1097 { }
1098};
1099
1100MODULE_DEVICE_TABLE(mdio, dp83640_tbl);
diff --git a/drivers/net/phy/dp83640_reg.h b/drivers/net/phy/dp83640_reg.h
new file mode 100644
index 000000000000..e7fe41117003
--- /dev/null
+++ b/drivers/net/phy/dp83640_reg.h
@@ -0,0 +1,267 @@
1/* dp83640_reg.h
2 * Generated by regen.tcl on Thu Feb 17 10:02:48 AM CET 2011
3 */
4#ifndef HAVE_DP83640_REGISTERS
5#define HAVE_DP83640_REGISTERS
6
7#define PAGE0 0x0000
8#define PHYCR2 0x001c /* PHY Control Register 2 */
9
10#define PAGE4 0x0004
11#define PTP_CTL 0x0014 /* PTP Control Register */
12#define PTP_TDR 0x0015 /* PTP Time Data Register */
13#define PTP_STS 0x0016 /* PTP Status Register */
14#define PTP_TSTS 0x0017 /* PTP Trigger Status Register */
15#define PTP_RATEL 0x0018 /* PTP Rate Low Register */
16#define PTP_RATEH 0x0019 /* PTP Rate High Register */
17#define PTP_RDCKSUM 0x001a /* PTP Read Checksum */
18#define PTP_WRCKSUM 0x001b /* PTP Write Checksum */
19#define PTP_TXTS 0x001c /* PTP Transmit Timestamp Register, in four 16-bit reads */
20#define PTP_RXTS 0x001d /* PTP Receive Timestamp Register, in six? 16-bit reads */
21#define PTP_ESTS 0x001e /* PTP Event Status Register */
22#define PTP_EDATA 0x001f /* PTP Event Data Register */
23
24#define PAGE5 0x0005
25#define PTP_TRIG 0x0014 /* PTP Trigger Configuration Register */
26#define PTP_EVNT 0x0015 /* PTP Event Configuration Register */
27#define PTP_TXCFG0 0x0016 /* PTP Transmit Configuration Register 0 */
28#define PTP_TXCFG1 0x0017 /* PTP Transmit Configuration Register 1 */
29#define PSF_CFG0 0x0018 /* PHY Status Frame Configuration Register 0 */
30#define PTP_RXCFG0 0x0019 /* PTP Receive Configuration Register 0 */
31#define PTP_RXCFG1 0x001a /* PTP Receive Configuration Register 1 */
32#define PTP_RXCFG2 0x001b /* PTP Receive Configuration Register 2 */
33#define PTP_RXCFG3 0x001c /* PTP Receive Configuration Register 3 */
34#define PTP_RXCFG4 0x001d /* PTP Receive Configuration Register 4 */
35#define PTP_TRDL 0x001e /* PTP Temporary Rate Duration Low Register */
36#define PTP_TRDH 0x001f /* PTP Temporary Rate Duration High Register */
37
38#define PAGE6 0x0006
39#define PTP_COC 0x0014 /* PTP Clock Output Control Register */
40#define PSF_CFG1 0x0015 /* PHY Status Frame Configuration Register 1 */
41#define PSF_CFG2 0x0016 /* PHY Status Frame Configuration Register 2 */
42#define PSF_CFG3 0x0017 /* PHY Status Frame Configuration Register 3 */
43#define PSF_CFG4 0x0018 /* PHY Status Frame Configuration Register 4 */
44#define PTP_SFDCFG 0x0019 /* PTP SFD Configuration Register */
45#define PTP_INTCTL 0x001a /* PTP Interrupt Control Register */
46#define PTP_CLKSRC 0x001b /* PTP Clock Source Register */
47#define PTP_ETR 0x001c /* PTP Ethernet Type Register */
48#define PTP_OFF 0x001d /* PTP Offset Register */
49#define PTP_GPIOMON 0x001e /* PTP GPIO Monitor Register */
50#define PTP_RXHASH 0x001f /* PTP Receive Hash Register */
51
52/* Bit definitions for the PHYCR2 register */
53#define BC_WRITE (1<<11) /* Broadcast Write Enable */
54
55/* Bit definitions for the PTP_CTL register */
56#define TRIG_SEL_SHIFT (10) /* PTP Trigger Select */
57#define TRIG_SEL_MASK (0x7)
58#define TRIG_DIS (1<<9) /* Disable PTP Trigger */
59#define TRIG_EN (1<<8) /* Enable PTP Trigger */
60#define TRIG_READ (1<<7) /* Read PTP Trigger */
61#define TRIG_LOAD (1<<6) /* Load PTP Trigger */
62#define PTP_RD_CLK (1<<5) /* Read PTP Clock */
63#define PTP_LOAD_CLK (1<<4) /* Load PTP Clock */
64#define PTP_STEP_CLK (1<<3) /* Step PTP Clock */
65#define PTP_ENABLE (1<<2) /* Enable PTP Clock */
66#define PTP_DISABLE (1<<1) /* Disable PTP Clock */
67#define PTP_RESET (1<<0) /* Reset PTP Clock */
68
69/* Bit definitions for the PTP_STS register */
70#define TXTS_RDY (1<<11) /* Transmit Timestamp Ready */
71#define RXTS_RDY (1<<10) /* Receive Timestamp Ready */
72#define TRIG_DONE (1<<9) /* PTP Trigger Done */
73#define EVENT_RDY (1<<8) /* PTP Event Timestamp Ready */
74#define TXTS_IE (1<<3) /* Transmit Timestamp Interrupt Enable */
75#define RXTS_IE (1<<2) /* Receive Timestamp Interrupt Enable */
76#define TRIG_IE (1<<1) /* Trigger Interrupt Enable */
77#define EVENT_IE (1<<0) /* Event Interrupt Enable */
78
79/* Bit definitions for the PTP_TSTS register */
80#define TRIG7_ERROR (1<<15) /* Trigger 7 Error */
81#define TRIG7_ACTIVE (1<<14) /* Trigger 7 Active */
82#define TRIG6_ERROR (1<<13) /* Trigger 6 Error */
83#define TRIG6_ACTIVE (1<<12) /* Trigger 6 Active */
84#define TRIG5_ERROR (1<<11) /* Trigger 5 Error */
85#define TRIG5_ACTIVE (1<<10) /* Trigger 5 Active */
86#define TRIG4_ERROR (1<<9) /* Trigger 4 Error */
87#define TRIG4_ACTIVE (1<<8) /* Trigger 4 Active */
88#define TRIG3_ERROR (1<<7) /* Trigger 3 Error */
89#define TRIG3_ACTIVE (1<<6) /* Trigger 3 Active */
90#define TRIG2_ERROR (1<<5) /* Trigger 2 Error */
91#define TRIG2_ACTIVE (1<<4) /* Trigger 2 Active */
92#define TRIG1_ERROR (1<<3) /* Trigger 1 Error */
93#define TRIG1_ACTIVE (1<<2) /* Trigger 1 Active */
94#define TRIG0_ERROR (1<<1) /* Trigger 0 Error */
95#define TRIG0_ACTIVE (1<<0) /* Trigger 0 Active */
96
97/* Bit definitions for the PTP_RATEH register */
98#define PTP_RATE_DIR (1<<15) /* PTP Rate Direction */
99#define PTP_TMP_RATE (1<<14) /* PTP Temporary Rate */
100#define PTP_RATE_HI_SHIFT (0) /* PTP Rate High 10-bits */
101#define PTP_RATE_HI_MASK (0x3ff)
102
103/* Bit definitions for the PTP_ESTS register */
104#define EVNTS_MISSED_SHIFT (8) /* Indicates number of events missed */
105#define EVNTS_MISSED_MASK (0x7)
106#define EVNT_TS_LEN_SHIFT (6) /* Indicates length of the Timestamp field in 16-bit words minus 1 */
107#define EVNT_TS_LEN_MASK (0x3)
108#define EVNT_RF (1<<5) /* Indicates whether the event is a rise or falling event */
109#define EVNT_NUM_SHIFT (2) /* Indicates Event Timestamp Unit which detected an event */
110#define EVNT_NUM_MASK (0x7)
111#define MULT_EVNT (1<<1) /* Indicates multiple events were detected at the same time */
112#define EVENT_DET (1<<0) /* PTP Event Detected */
113
114/* Bit definitions for the PTP_EDATA register */
115#define E7_RISE (1<<15) /* Indicates direction of Event 7 */
116#define E7_DET (1<<14) /* Indicates Event 7 detected */
117#define E6_RISE (1<<13) /* Indicates direction of Event 6 */
118#define E6_DET (1<<12) /* Indicates Event 6 detected */
119#define E5_RISE (1<<11) /* Indicates direction of Event 5 */
120#define E5_DET (1<<10) /* Indicates Event 5 detected */
121#define E4_RISE (1<<9) /* Indicates direction of Event 4 */
122#define E4_DET (1<<8) /* Indicates Event 4 detected */
123#define E3_RISE (1<<7) /* Indicates direction of Event 3 */
124#define E3_DET (1<<6) /* Indicates Event 3 detected */
125#define E2_RISE (1<<5) /* Indicates direction of Event 2 */
126#define E2_DET (1<<4) /* Indicates Event 2 detected */
127#define E1_RISE (1<<3) /* Indicates direction of Event 1 */
128#define E1_DET (1<<2) /* Indicates Event 1 detected */
129#define E0_RISE (1<<1) /* Indicates direction of Event 0 */
130#define E0_DET (1<<0) /* Indicates Event 0 detected */
131
132/* Bit definitions for the PTP_TRIG register */
133#define TRIG_PULSE (1<<15) /* generate a Pulse rather than a single edge */
134#define TRIG_PER (1<<14) /* generate a periodic signal */
135#define TRIG_IF_LATE (1<<13) /* trigger immediately if already past */
136#define TRIG_NOTIFY (1<<12) /* Trigger Notification Enable */
137#define TRIG_GPIO_SHIFT (8) /* Trigger GPIO Connection, value 1-12 */
138#define TRIG_GPIO_MASK (0xf)
139#define TRIG_TOGGLE (1<<7) /* Trigger Toggle Mode Enable */
140#define TRIG_CSEL_SHIFT (1) /* Trigger Configuration Select */
141#define TRIG_CSEL_MASK (0x7)
142#define TRIG_WR (1<<0) /* Trigger Configuration Write */
143
144/* Bit definitions for the PTP_EVNT register */
145#define EVNT_RISE (1<<14) /* Event Rise Detect Enable */
146#define EVNT_FALL (1<<13) /* Event Fall Detect Enable */
147#define EVNT_SINGLE (1<<12) /* enable single event capture operation */
148#define EVNT_GPIO_SHIFT (8) /* Event GPIO Connection, value 1-12 */
149#define EVNT_GPIO_MASK (0xf)
150#define EVNT_SEL_SHIFT (1) /* Event Select */
151#define EVNT_SEL_MASK (0x7)
152#define EVNT_WR (1<<0) /* Event Configuration Write */
153
154/* Bit definitions for the PTP_TXCFG0 register */
155#define SYNC_1STEP (1<<15) /* insert timestamp into transmit Sync Messages */
156#define DR_INSERT (1<<13) /* Insert Delay_Req Timestamp in Delay_Resp (dangerous) */
157#define NTP_TS_EN (1<<12) /* Enable Timestamping of NTP Packets */
158#define IGNORE_2STEP (1<<11) /* Ignore Two_Step flag for One-Step operation */
159#define CRC_1STEP (1<<10) /* Disable checking of CRC for One-Step operation */
160#define CHK_1STEP (1<<9) /* Enable UDP Checksum correction for One-Step Operation */
161#define IP1588_EN (1<<8) /* Enable IEEE 1588 defined IP address filter */
162#define TX_L2_EN (1<<7) /* Layer2 Timestamp Enable */
163#define TX_IPV6_EN (1<<6) /* IPv6 Timestamp Enable */
164#define TX_IPV4_EN (1<<5) /* IPv4 Timestamp Enable */
165#define TX_PTP_VER_SHIFT (1) /* Enable Timestamp capture for IEEE 1588 version X */
166#define TX_PTP_VER_MASK (0xf)
167#define TX_TS_EN (1<<0) /* Transmit Timestamp Enable */
168
169/* Bit definitions for the PTP_TXCFG1 register */
170#define BYTE0_MASK_SHIFT (8) /* Bit mask to be used for matching Byte0 of the PTP Message */
171#define BYTE0_MASK_MASK (0xff)
172#define BYTE0_DATA_SHIFT (0) /* Data to be used for matching Byte0 of the PTP Message */
173#define BYTE0_DATA_MASK (0xff)
174
175/* Bit definitions for the PSF_CFG0 register */
176#define MAC_SRC_ADD_SHIFT (11) /* Status Frame Mac Source Address */
177#define MAC_SRC_ADD_MASK (0x3)
178#define MIN_PRE_SHIFT (8) /* Status Frame Minimum Preamble */
179#define MIN_PRE_MASK (0x7)
180#define PSF_ENDIAN (1<<7) /* Status Frame Endian Control */
181#define PSF_IPV4 (1<<6) /* Status Frame IPv4 Enable */
182#define PSF_PCF_RD (1<<5) /* Control Frame Read PHY Status Frame Enable */
183#define PSF_ERR_EN (1<<4) /* Error PHY Status Frame Enable */
184#define PSF_TXTS_EN (1<<3) /* Transmit Timestamp PHY Status Frame Enable */
185#define PSF_RXTS_EN (1<<2) /* Receive Timestamp PHY Status Frame Enable */
186#define PSF_TRIG_EN (1<<1) /* Trigger PHY Status Frame Enable */
187#define PSF_EVNT_EN (1<<0) /* Event PHY Status Frame Enable */
188
189/* Bit definitions for the PTP_RXCFG0 register */
190#define DOMAIN_EN (1<<15) /* Domain Match Enable */
191#define ALT_MAST_DIS (1<<14) /* Alternate Master Timestamp Disable */
192#define USER_IP_SEL (1<<13) /* Selects portion of IP address accessible thru PTP_RXCFG2 */
193#define USER_IP_EN (1<<12) /* Enable User-programmed IP address filter */
194#define RX_SLAVE (1<<11) /* Receive Slave Only */
195#define IP1588_EN_SHIFT (8) /* Enable IEEE 1588 defined IP address filters */
196#define IP1588_EN_MASK (0xf)
197#define RX_L2_EN (1<<7) /* Layer2 Timestamp Enable */
198#define RX_IPV6_EN (1<<6) /* IPv6 Timestamp Enable */
199#define RX_IPV4_EN (1<<5) /* IPv4 Timestamp Enable */
200#define RX_PTP_VER_SHIFT (1) /* Enable Timestamp capture for IEEE 1588 version X */
201#define RX_PTP_VER_MASK (0xf)
202#define RX_TS_EN (1<<0) /* Receive Timestamp Enable */
203
204/* Bit definitions for the PTP_RXCFG1 register */
205#define BYTE0_MASK_SHIFT (8) /* Bit mask to be used for matching Byte0 of the PTP Message */
206#define BYTE0_MASK_MASK (0xff)
207#define BYTE0_DATA_SHIFT (0) /* Data to be used for matching Byte0 of the PTP Message */
208#define BYTE0_DATA_MASK (0xff)
209
210/* Bit definitions for the PTP_RXCFG3 register */
211#define TS_MIN_IFG_SHIFT (12) /* Minimum Inter-frame Gap */
212#define TS_MIN_IFG_MASK (0xf)
213#define ACC_UDP (1<<11) /* Record Timestamp if UDP Checksum Error */
214#define ACC_CRC (1<<10) /* Record Timestamp if CRC Error */
215#define TS_APPEND (1<<9) /* Append Timestamp for L2 */
216#define TS_INSERT (1<<8) /* Enable Timestamp Insertion */
217#define PTP_DOMAIN_SHIFT (0) /* PTP Message domainNumber field */
218#define PTP_DOMAIN_MASK (0xff)
219
220/* Bit definitions for the PTP_RXCFG4 register */
221#define IPV4_UDP_MOD (1<<15) /* Enable IPV4 UDP Modification */
222#define TS_SEC_EN (1<<14) /* Enable Timestamp Seconds */
223#define TS_SEC_LEN_SHIFT (12) /* Inserted Timestamp Seconds Length */
224#define TS_SEC_LEN_MASK (0x3)
225#define RXTS_NS_OFF_SHIFT (6) /* Receive Timestamp Nanoseconds offset */
226#define RXTS_NS_OFF_MASK (0x3f)
227#define RXTS_SEC_OFF_SHIFT (0) /* Receive Timestamp Seconds offset */
228#define RXTS_SEC_OFF_MASK (0x3f)
229
230/* Bit definitions for the PTP_COC register */
231#define PTP_CLKOUT_EN (1<<15) /* PTP Clock Output Enable */
232#define PTP_CLKOUT_SEL (1<<14) /* PTP Clock Output Source Select */
233#define PTP_CLKOUT_SPEEDSEL (1<<13) /* PTP Clock Output I/O Speed Select */
234#define PTP_CLKDIV_SHIFT (0) /* PTP Clock Divide-by Value */
235#define PTP_CLKDIV_MASK (0xff)
236
237/* Bit definitions for the PSF_CFG1 register */
238#define PTPRESERVED_SHIFT (12) /* PTP v2 reserved field */
239#define PTPRESERVED_MASK (0xf)
240#define VERSIONPTP_SHIFT (8) /* PTP v2 versionPTP field */
241#define VERSIONPTP_MASK (0xf)
242#define TRANSPORT_SPECIFIC_SHIFT (4) /* PTP v2 Header transportSpecific field */
243#define TRANSPORT_SPECIFIC_MASK (0xf)
244#define MESSAGETYPE_SHIFT (0) /* PTP v2 messageType field */
245#define MESSAGETYPE_MASK (0xf)
246
247/* Bit definitions for the PTP_SFDCFG register */
248#define TX_SFD_GPIO_SHIFT (4) /* TX SFD GPIO Select, value 1-12 */
249#define TX_SFD_GPIO_MASK (0xf)
250#define RX_SFD_GPIO_SHIFT (0) /* RX SFD GPIO Select, value 1-12 */
251#define RX_SFD_GPIO_MASK (0xf)
252
253/* Bit definitions for the PTP_INTCTL register */
254#define PTP_INT_GPIO_SHIFT (0) /* PTP Interrupt GPIO Select */
255#define PTP_INT_GPIO_MASK (0xf)
256
257/* Bit definitions for the PTP_CLKSRC register */
258#define CLK_SRC_SHIFT (14) /* PTP Clock Source Select */
259#define CLK_SRC_MASK (0x3)
260#define CLK_SRC_PER_SHIFT (0) /* PTP Clock Source Period */
261#define CLK_SRC_PER_MASK (0x7f)
262
263/* Bit definitions for the PTP_OFF register */
264#define PTP_OFFSET_SHIFT (0) /* PTP Message offset from preceding header */
265#define PTP_OFFSET_MASK (0xff)
266
267#endif
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
new file mode 100644
index 000000000000..68d720102296
--- /dev/null
+++ b/drivers/ptp/Kconfig
@@ -0,0 +1,75 @@
1#
2# PTP clock support configuration
3#
4
5menu "PTP clock support"
6
7comment "Enable Device Drivers -> PPS to see the PTP clock options."
8 depends on PPS=n
9
10config PTP_1588_CLOCK
11 tristate "PTP clock support"
12 depends on EXPERIMENTAL
13 depends on PPS
14 help
15 The IEEE 1588 standard defines a method to precisely
16 synchronize distributed clocks over Ethernet networks. The
17 standard defines a Precision Time Protocol (PTP), which can
18 be used to achieve synchronization within a few dozen
19 microseconds. In addition, with the help of special hardware
20 time stamping units, it can be possible to achieve
21 synchronization to within a few hundred nanoseconds.
22
23 This driver adds support for PTP clocks as character
24 devices. If you want to use a PTP clock, then you should
25 also enable at least one clock driver as well.
26
27 To compile this driver as a module, choose M here: the module
28 will be called ptp.
29
30config PTP_1588_CLOCK_GIANFAR
31 tristate "Freescale eTSEC as PTP clock"
32 depends on PTP_1588_CLOCK
33 depends on GIANFAR
34 help
35 This driver adds support for using the eTSEC as a PTP
36 clock. This clock is only useful if your PTP programs are
37 getting hardware time stamps on the PTP Ethernet packets
38 using the SO_TIMESTAMPING API.
39
40 To compile this driver as a module, choose M here: the module
41 will be called gianfar_ptp.
42
43config PTP_1588_CLOCK_IXP46X
44 tristate "Intel IXP46x as PTP clock"
45 depends on PTP_1588_CLOCK
46 depends on IXP4XX_ETH
47 help
48 This driver adds support for using the IXP46X as a PTP
49 clock. This clock is only useful if your PTP programs are
50 getting hardware time stamps on the PTP Ethernet packets
51 using the SO_TIMESTAMPING API.
52
53 To compile this driver as a module, choose M here: the module
54 will be called ptp_ixp46x.
55
56comment "Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks."
57 depends on PTP_1588_CLOCK && (PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n)
58
59config DP83640_PHY
60 tristate "Driver for the National Semiconductor DP83640 PHYTER"
61 depends on PTP_1588_CLOCK
62 depends on NETWORK_PHY_TIMESTAMPING
63 depends on PHYLIB
64 ---help---
65 Supports the DP83640 PHYTER with IEEE 1588 features.
66
67 This driver adds support for using the DP83640 as a PTP
68 clock. This clock is only useful if your PTP programs are
69 getting hardware time stamps on the PTP Ethernet packets
70 using the SO_TIMESTAMPING API.
71
72 In order for this to work, your MAC driver must also
73 implement the skb_tx_timetamp() function.
74
75endmenu
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
new file mode 100644
index 000000000000..f6933e83de72
--- /dev/null
+++ b/drivers/ptp/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for PTP 1588 clock support.
3#
4
5ptp-y := ptp_clock.o ptp_chardev.o ptp_sysfs.o
6obj-$(CONFIG_PTP_1588_CLOCK) += ptp.o
7obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
new file mode 100644
index 000000000000..a8d03aeb4051
--- /dev/null
+++ b/drivers/ptp/ptp_chardev.c
@@ -0,0 +1,159 @@
1/*
2 * PTP 1588 clock support - character device implementation.
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/module.h>
21#include <linux/posix-clock.h>
22#include <linux/poll.h>
23#include <linux/sched.h>
24
25#include "ptp_private.h"
26
27int ptp_open(struct posix_clock *pc, fmode_t fmode)
28{
29 return 0;
30}
31
32long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
33{
34 struct ptp_clock_caps caps;
35 struct ptp_clock_request req;
36 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
37 struct ptp_clock_info *ops = ptp->info;
38 int enable, err = 0;
39
40 switch (cmd) {
41
42 case PTP_CLOCK_GETCAPS:
43 memset(&caps, 0, sizeof(caps));
44 caps.max_adj = ptp->info->max_adj;
45 caps.n_alarm = ptp->info->n_alarm;
46 caps.n_ext_ts = ptp->info->n_ext_ts;
47 caps.n_per_out = ptp->info->n_per_out;
48 caps.pps = ptp->info->pps;
49 err = copy_to_user((void __user *)arg, &caps, sizeof(caps));
50 break;
51
52 case PTP_EXTTS_REQUEST:
53 if (copy_from_user(&req.extts, (void __user *)arg,
54 sizeof(req.extts))) {
55 err = -EFAULT;
56 break;
57 }
58 if (req.extts.index >= ops->n_ext_ts) {
59 err = -EINVAL;
60 break;
61 }
62 req.type = PTP_CLK_REQ_EXTTS;
63 enable = req.extts.flags & PTP_ENABLE_FEATURE ? 1 : 0;
64 err = ops->enable(ops, &req, enable);
65 break;
66
67 case PTP_PEROUT_REQUEST:
68 if (copy_from_user(&req.perout, (void __user *)arg,
69 sizeof(req.perout))) {
70 err = -EFAULT;
71 break;
72 }
73 if (req.perout.index >= ops->n_per_out) {
74 err = -EINVAL;
75 break;
76 }
77 req.type = PTP_CLK_REQ_PEROUT;
78 enable = req.perout.period.sec || req.perout.period.nsec;
79 err = ops->enable(ops, &req, enable);
80 break;
81
82 case PTP_ENABLE_PPS:
83 if (!capable(CAP_SYS_TIME))
84 return -EPERM;
85 req.type = PTP_CLK_REQ_PPS;
86 enable = arg ? 1 : 0;
87 err = ops->enable(ops, &req, enable);
88 break;
89
90 default:
91 err = -ENOTTY;
92 break;
93 }
94 return err;
95}
96
97unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
98{
99 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
100
101 poll_wait(fp, &ptp->tsev_wq, wait);
102
103 return queue_cnt(&ptp->tsevq) ? POLLIN : 0;
104}
105
106ssize_t ptp_read(struct posix_clock *pc,
107 uint rdflags, char __user *buf, size_t cnt)
108{
109 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
110 struct timestamp_event_queue *queue = &ptp->tsevq;
111 struct ptp_extts_event event[PTP_BUF_TIMESTAMPS];
112 unsigned long flags;
113 size_t qcnt, i;
114
115 if (cnt % sizeof(struct ptp_extts_event) != 0)
116 return -EINVAL;
117
118 if (cnt > sizeof(event))
119 cnt = sizeof(event);
120
121 cnt = cnt / sizeof(struct ptp_extts_event);
122
123 if (mutex_lock_interruptible(&ptp->tsevq_mux))
124 return -ERESTARTSYS;
125
126 if (wait_event_interruptible(ptp->tsev_wq,
127 ptp->defunct || queue_cnt(queue))) {
128 mutex_unlock(&ptp->tsevq_mux);
129 return -ERESTARTSYS;
130 }
131
132 if (ptp->defunct)
133 return -ENODEV;
134
135 spin_lock_irqsave(&queue->lock, flags);
136
137 qcnt = queue_cnt(queue);
138
139 if (cnt > qcnt)
140 cnt = qcnt;
141
142 for (i = 0; i < cnt; i++) {
143 event[i] = queue->buf[queue->head];
144 queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
145 }
146
147 spin_unlock_irqrestore(&queue->lock, flags);
148
149 cnt = cnt * sizeof(struct ptp_extts_event);
150
151 mutex_unlock(&ptp->tsevq_mux);
152
153 if (copy_to_user(buf, event, cnt)) {
154 mutex_unlock(&ptp->tsevq_mux);
155 return -EFAULT;
156 }
157
158 return cnt;
159}
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
new file mode 100644
index 000000000000..cf3f9997546d
--- /dev/null
+++ b/drivers/ptp/ptp_clock.c
@@ -0,0 +1,343 @@
1/*
2 * PTP 1588 clock support
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/bitops.h>
21#include <linux/device.h>
22#include <linux/err.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/posix-clock.h>
27#include <linux/pps_kernel.h>
28#include <linux/slab.h>
29#include <linux/syscalls.h>
30#include <linux/uaccess.h>
31
32#include "ptp_private.h"
33
34#define PTP_MAX_ALARMS 4
35#define PTP_MAX_CLOCKS 8
36#define PTP_PPS_DEFAULTS (PPS_CAPTUREASSERT | PPS_OFFSETASSERT)
37#define PTP_PPS_EVENT PPS_CAPTUREASSERT
38#define PTP_PPS_MODE (PTP_PPS_DEFAULTS | PPS_CANWAIT | PPS_TSFMT_TSPEC)
39
40/* private globals */
41
42static dev_t ptp_devt;
43static struct class *ptp_class;
44
45static DECLARE_BITMAP(ptp_clocks_map, PTP_MAX_CLOCKS);
46static DEFINE_MUTEX(ptp_clocks_mutex); /* protects 'ptp_clocks_map' */
47
48/* time stamp event queue operations */
49
50static inline int queue_free(struct timestamp_event_queue *q)
51{
52 return PTP_MAX_TIMESTAMPS - queue_cnt(q) - 1;
53}
54
55static void enqueue_external_timestamp(struct timestamp_event_queue *queue,
56 struct ptp_clock_event *src)
57{
58 struct ptp_extts_event *dst;
59 unsigned long flags;
60 s64 seconds;
61 u32 remainder;
62
63 seconds = div_u64_rem(src->timestamp, 1000000000, &remainder);
64
65 spin_lock_irqsave(&queue->lock, flags);
66
67 dst = &queue->buf[queue->tail];
68 dst->index = src->index;
69 dst->t.sec = seconds;
70 dst->t.nsec = remainder;
71
72 if (!queue_free(queue))
73 queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
74
75 queue->tail = (queue->tail + 1) % PTP_MAX_TIMESTAMPS;
76
77 spin_unlock_irqrestore(&queue->lock, flags);
78}
79
80static s32 scaled_ppm_to_ppb(long ppm)
81{
82 /*
83 * The 'freq' field in the 'struct timex' is in parts per
84 * million, but with a 16 bit binary fractional field.
85 *
86 * We want to calculate
87 *
88 * ppb = scaled_ppm * 1000 / 2^16
89 *
90 * which simplifies to
91 *
92 * ppb = scaled_ppm * 125 / 2^13
93 */
94 s64 ppb = 1 + ppm;
95 ppb *= 125;
96 ppb >>= 13;
97 return (s32) ppb;
98}
99
100/* posix clock implementation */
101
102static int ptp_clock_getres(struct posix_clock *pc, struct timespec *tp)
103{
104 return 1; /* always round timer functions to one nanosecond */
105}
106
107static int ptp_clock_settime(struct posix_clock *pc, const struct timespec *tp)
108{
109 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
110 return ptp->info->settime(ptp->info, tp);
111}
112
113static int ptp_clock_gettime(struct posix_clock *pc, struct timespec *tp)
114{
115 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
116 return ptp->info->gettime(ptp->info, tp);
117}
118
119static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx)
120{
121 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
122 struct ptp_clock_info *ops;
123 int err = -EOPNOTSUPP;
124
125 ops = ptp->info;
126
127 if (tx->modes & ADJ_SETOFFSET) {
128 struct timespec ts;
129 ktime_t kt;
130 s64 delta;
131
132 ts.tv_sec = tx->time.tv_sec;
133 ts.tv_nsec = tx->time.tv_usec;
134
135 if (!(tx->modes & ADJ_NANO))
136 ts.tv_nsec *= 1000;
137
138 if ((unsigned long) ts.tv_nsec >= NSEC_PER_SEC)
139 return -EINVAL;
140
141 kt = timespec_to_ktime(ts);
142 delta = ktime_to_ns(kt);
143 err = ops->adjtime(ops, delta);
144
145 } else if (tx->modes & ADJ_FREQUENCY) {
146
147 err = ops->adjfreq(ops, scaled_ppm_to_ppb(tx->freq));
148 }
149
150 return err;
151}
152
153static struct posix_clock_operations ptp_clock_ops = {
154 .owner = THIS_MODULE,
155 .clock_adjtime = ptp_clock_adjtime,
156 .clock_gettime = ptp_clock_gettime,
157 .clock_getres = ptp_clock_getres,
158 .clock_settime = ptp_clock_settime,
159 .ioctl = ptp_ioctl,
160 .open = ptp_open,
161 .poll = ptp_poll,
162 .read = ptp_read,
163};
164
165static void delete_ptp_clock(struct posix_clock *pc)
166{
167 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
168
169 mutex_destroy(&ptp->tsevq_mux);
170
171 /* Remove the clock from the bit map. */
172 mutex_lock(&ptp_clocks_mutex);
173 clear_bit(ptp->index, ptp_clocks_map);
174 mutex_unlock(&ptp_clocks_mutex);
175
176 kfree(ptp);
177}
178
179/* public interface */
180
181struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info)
182{
183 struct ptp_clock *ptp;
184 int err = 0, index, major = MAJOR(ptp_devt);
185
186 if (info->n_alarm > PTP_MAX_ALARMS)
187 return ERR_PTR(-EINVAL);
188
189 /* Find a free clock slot and reserve it. */
190 err = -EBUSY;
191 mutex_lock(&ptp_clocks_mutex);
192 index = find_first_zero_bit(ptp_clocks_map, PTP_MAX_CLOCKS);
193 if (index < PTP_MAX_CLOCKS)
194 set_bit(index, ptp_clocks_map);
195 else
196 goto no_slot;
197
198 /* Initialize a clock structure. */
199 err = -ENOMEM;
200 ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL);
201 if (ptp == NULL)
202 goto no_memory;
203
204 ptp->clock.ops = ptp_clock_ops;
205 ptp->clock.release = delete_ptp_clock;
206 ptp->info = info;
207 ptp->devid = MKDEV(major, index);
208 ptp->index = index;
209 spin_lock_init(&ptp->tsevq.lock);
210 mutex_init(&ptp->tsevq_mux);
211 init_waitqueue_head(&ptp->tsev_wq);
212
213 /* Create a new device in our class. */
214 ptp->dev = device_create(ptp_class, NULL, ptp->devid, ptp,
215 "ptp%d", ptp->index);
216 if (IS_ERR(ptp->dev))
217 goto no_device;
218
219 dev_set_drvdata(ptp->dev, ptp);
220
221 err = ptp_populate_sysfs(ptp);
222 if (err)
223 goto no_sysfs;
224
225 /* Register a new PPS source. */
226 if (info->pps) {
227 struct pps_source_info pps;
228 memset(&pps, 0, sizeof(pps));
229 snprintf(pps.name, PPS_MAX_NAME_LEN, "ptp%d", index);
230 pps.mode = PTP_PPS_MODE;
231 pps.owner = info->owner;
232 ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
233 if (!ptp->pps_source) {
234 pr_err("failed to register pps source\n");
235 goto no_pps;
236 }
237 }
238
239 /* Create a posix clock. */
240 err = posix_clock_register(&ptp->clock, ptp->devid);
241 if (err) {
242 pr_err("failed to create posix clock\n");
243 goto no_clock;
244 }
245
246 mutex_unlock(&ptp_clocks_mutex);
247 return ptp;
248
249no_clock:
250 if (ptp->pps_source)
251 pps_unregister_source(ptp->pps_source);
252no_pps:
253 ptp_cleanup_sysfs(ptp);
254no_sysfs:
255 device_destroy(ptp_class, ptp->devid);
256no_device:
257 mutex_destroy(&ptp->tsevq_mux);
258 kfree(ptp);
259no_memory:
260 clear_bit(index, ptp_clocks_map);
261no_slot:
262 mutex_unlock(&ptp_clocks_mutex);
263 return ERR_PTR(err);
264}
265EXPORT_SYMBOL(ptp_clock_register);
266
267int ptp_clock_unregister(struct ptp_clock *ptp)
268{
269 ptp->defunct = 1;
270 wake_up_interruptible(&ptp->tsev_wq);
271
272 /* Release the clock's resources. */
273 if (ptp->pps_source)
274 pps_unregister_source(ptp->pps_source);
275 ptp_cleanup_sysfs(ptp);
276 device_destroy(ptp_class, ptp->devid);
277
278 posix_clock_unregister(&ptp->clock);
279 return 0;
280}
281EXPORT_SYMBOL(ptp_clock_unregister);
282
283void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
284{
285 struct pps_event_time evt;
286
287 switch (event->type) {
288
289 case PTP_CLOCK_ALARM:
290 break;
291
292 case PTP_CLOCK_EXTTS:
293 enqueue_external_timestamp(&ptp->tsevq, event);
294 wake_up_interruptible(&ptp->tsev_wq);
295 break;
296
297 case PTP_CLOCK_PPS:
298 pps_get_ts(&evt);
299 pps_event(ptp->pps_source, &evt, PTP_PPS_EVENT, NULL);
300 break;
301 }
302}
303EXPORT_SYMBOL(ptp_clock_event);
304
305/* module operations */
306
307static void __exit ptp_exit(void)
308{
309 class_destroy(ptp_class);
310 unregister_chrdev_region(ptp_devt, PTP_MAX_CLOCKS);
311}
312
313static int __init ptp_init(void)
314{
315 int err;
316
317 ptp_class = class_create(THIS_MODULE, "ptp");
318 if (IS_ERR(ptp_class)) {
319 pr_err("ptp: failed to allocate class\n");
320 return PTR_ERR(ptp_class);
321 }
322
323 err = alloc_chrdev_region(&ptp_devt, 0, PTP_MAX_CLOCKS, "ptp");
324 if (err < 0) {
325 pr_err("ptp: failed to allocate device region\n");
326 goto no_region;
327 }
328
329 ptp_class->dev_attrs = ptp_dev_attrs;
330 pr_info("PTP clock support registered\n");
331 return 0;
332
333no_region:
334 class_destroy(ptp_class);
335 return err;
336}
337
338subsys_initcall(ptp_init);
339module_exit(ptp_exit);
340
341MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
342MODULE_DESCRIPTION("PTP clocks support");
343MODULE_LICENSE("GPL");
diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c
new file mode 100644
index 000000000000..803d665b15ef
--- /dev/null
+++ b/drivers/ptp/ptp_ixp46x.c
@@ -0,0 +1,332 @@
1/*
2 * PTP 1588 clock using the IXP46X
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/device.h>
21#include <linux/err.h>
22#include <linux/gpio.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/io.h>
26#include <linux/irq.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29
30#include <linux/ptp_clock_kernel.h>
31#include <mach/ixp46x_ts.h>
32
33#define DRIVER "ptp_ixp46x"
34#define N_EXT_TS 2
35#define MASTER_GPIO 8
36#define MASTER_IRQ 25
37#define SLAVE_GPIO 7
38#define SLAVE_IRQ 24
39
40struct ixp_clock {
41 struct ixp46x_ts_regs *regs;
42 struct ptp_clock *ptp_clock;
43 struct ptp_clock_info caps;
44 int exts0_enabled;
45 int exts1_enabled;
46};
47
48DEFINE_SPINLOCK(register_lock);
49
50/*
51 * Register access functions
52 */
53
54static u64 ixp_systime_read(struct ixp46x_ts_regs *regs)
55{
56 u64 ns;
57 u32 lo, hi;
58
59 lo = __raw_readl(&regs->systime_lo);
60 hi = __raw_readl(&regs->systime_hi);
61
62 ns = ((u64) hi) << 32;
63 ns |= lo;
64 ns <<= TICKS_NS_SHIFT;
65
66 return ns;
67}
68
69static void ixp_systime_write(struct ixp46x_ts_regs *regs, u64 ns)
70{
71 u32 hi, lo;
72
73 ns >>= TICKS_NS_SHIFT;
74 hi = ns >> 32;
75 lo = ns & 0xffffffff;
76
77 __raw_writel(lo, &regs->systime_lo);
78 __raw_writel(hi, &regs->systime_hi);
79}
80
81/*
82 * Interrupt service routine
83 */
84
85static irqreturn_t isr(int irq, void *priv)
86{
87 struct ixp_clock *ixp_clock = priv;
88 struct ixp46x_ts_regs *regs = ixp_clock->regs;
89 struct ptp_clock_event event;
90 u32 ack = 0, lo, hi, val;
91
92 val = __raw_readl(&regs->event);
93
94 if (val & TSER_SNS) {
95 ack |= TSER_SNS;
96 if (ixp_clock->exts0_enabled) {
97 hi = __raw_readl(&regs->asms_hi);
98 lo = __raw_readl(&regs->asms_lo);
99 event.type = PTP_CLOCK_EXTTS;
100 event.index = 0;
101 event.timestamp = ((u64) hi) << 32;
102 event.timestamp |= lo;
103 event.timestamp <<= TICKS_NS_SHIFT;
104 ptp_clock_event(ixp_clock->ptp_clock, &event);
105 }
106 }
107
108 if (val & TSER_SNM) {
109 ack |= TSER_SNM;
110 if (ixp_clock->exts1_enabled) {
111 hi = __raw_readl(&regs->amms_hi);
112 lo = __raw_readl(&regs->amms_lo);
113 event.type = PTP_CLOCK_EXTTS;
114 event.index = 1;
115 event.timestamp = ((u64) hi) << 32;
116 event.timestamp |= lo;
117 event.timestamp <<= TICKS_NS_SHIFT;
118 ptp_clock_event(ixp_clock->ptp_clock, &event);
119 }
120 }
121
122 if (val & TTIPEND)
123 ack |= TTIPEND; /* this bit seems to be always set */
124
125 if (ack) {
126 __raw_writel(ack, &regs->event);
127 return IRQ_HANDLED;
128 } else
129 return IRQ_NONE;
130}
131
132/*
133 * PTP clock operations
134 */
135
136static int ptp_ixp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
137{
138 u64 adj;
139 u32 diff, addend;
140 int neg_adj = 0;
141 struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
142 struct ixp46x_ts_regs *regs = ixp_clock->regs;
143
144 if (ppb < 0) {
145 neg_adj = 1;
146 ppb = -ppb;
147 }
148 addend = DEFAULT_ADDEND;
149 adj = addend;
150 adj *= ppb;
151 diff = div_u64(adj, 1000000000ULL);
152
153 addend = neg_adj ? addend - diff : addend + diff;
154
155 __raw_writel(addend, &regs->addend);
156
157 return 0;
158}
159
160static int ptp_ixp_adjtime(struct ptp_clock_info *ptp, s64 delta)
161{
162 s64 now;
163 unsigned long flags;
164 struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
165 struct ixp46x_ts_regs *regs = ixp_clock->regs;
166
167 spin_lock_irqsave(&register_lock, flags);
168
169 now = ixp_systime_read(regs);
170 now += delta;
171 ixp_systime_write(regs, now);
172
173 spin_unlock_irqrestore(&register_lock, flags);
174
175 return 0;
176}
177
178static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
179{
180 u64 ns;
181 u32 remainder;
182 unsigned long flags;
183 struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
184 struct ixp46x_ts_regs *regs = ixp_clock->regs;
185
186 spin_lock_irqsave(&register_lock, flags);
187
188 ns = ixp_systime_read(regs);
189
190 spin_unlock_irqrestore(&register_lock, flags);
191
192 ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
193 ts->tv_nsec = remainder;
194 return 0;
195}
196
197static int ptp_ixp_settime(struct ptp_clock_info *ptp,
198 const struct timespec *ts)
199{
200 u64 ns;
201 unsigned long flags;
202 struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
203 struct ixp46x_ts_regs *regs = ixp_clock->regs;
204
205 ns = ts->tv_sec * 1000000000ULL;
206 ns += ts->tv_nsec;
207
208 spin_lock_irqsave(&register_lock, flags);
209
210 ixp_systime_write(regs, ns);
211
212 spin_unlock_irqrestore(&register_lock, flags);
213
214 return 0;
215}
216
217static int ptp_ixp_enable(struct ptp_clock_info *ptp,
218 struct ptp_clock_request *rq, int on)
219{
220 struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
221
222 switch (rq->type) {
223 case PTP_CLK_REQ_EXTTS:
224 switch (rq->extts.index) {
225 case 0:
226 ixp_clock->exts0_enabled = on ? 1 : 0;
227 break;
228 case 1:
229 ixp_clock->exts1_enabled = on ? 1 : 0;
230 break;
231 default:
232 return -EINVAL;
233 }
234 return 0;
235 default:
236 break;
237 }
238
239 return -EOPNOTSUPP;
240}
241
242static struct ptp_clock_info ptp_ixp_caps = {
243 .owner = THIS_MODULE,
244 .name = "IXP46X timer",
245 .max_adj = 66666655,
246 .n_ext_ts = N_EXT_TS,
247 .pps = 0,
248 .adjfreq = ptp_ixp_adjfreq,
249 .adjtime = ptp_ixp_adjtime,
250 .gettime = ptp_ixp_gettime,
251 .settime = ptp_ixp_settime,
252 .enable = ptp_ixp_enable,
253};
254
255/* module operations */
256
257static struct ixp_clock ixp_clock;
258
259static int setup_interrupt(int gpio)
260{
261 int irq;
262
263 gpio_line_config(gpio, IXP4XX_GPIO_IN);
264
265 irq = gpio_to_irq(gpio);
266
267 if (NO_IRQ == irq)
268 return NO_IRQ;
269
270 if (irq_set_irq_type(irq, IRQF_TRIGGER_FALLING)) {
271 pr_err("cannot set trigger type for irq %d\n", irq);
272 return NO_IRQ;
273 }
274
275 if (request_irq(irq, isr, 0, DRIVER, &ixp_clock)) {
276 pr_err("request_irq failed for irq %d\n", irq);
277 return NO_IRQ;
278 }
279
280 return irq;
281}
282
283static void __exit ptp_ixp_exit(void)
284{
285 free_irq(MASTER_IRQ, &ixp_clock);
286 free_irq(SLAVE_IRQ, &ixp_clock);
287 ptp_clock_unregister(ixp_clock.ptp_clock);
288}
289
290static int __init ptp_ixp_init(void)
291{
292 if (!cpu_is_ixp46x())
293 return -ENODEV;
294
295 ixp_clock.regs =
296 (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
297
298 ixp_clock.caps = ptp_ixp_caps;
299
300 ixp_clock.ptp_clock = ptp_clock_register(&ixp_clock.caps);
301
302 if (IS_ERR(ixp_clock.ptp_clock))
303 return PTR_ERR(ixp_clock.ptp_clock);
304
305 __raw_writel(DEFAULT_ADDEND, &ixp_clock.regs->addend);
306 __raw_writel(1, &ixp_clock.regs->trgt_lo);
307 __raw_writel(0, &ixp_clock.regs->trgt_hi);
308 __raw_writel(TTIPEND, &ixp_clock.regs->event);
309
310 if (MASTER_IRQ != setup_interrupt(MASTER_GPIO)) {
311 pr_err("failed to setup gpio %d as irq\n", MASTER_GPIO);
312 goto no_master;
313 }
314 if (SLAVE_IRQ != setup_interrupt(SLAVE_GPIO)) {
315 pr_err("failed to setup gpio %d as irq\n", SLAVE_GPIO);
316 goto no_slave;
317 }
318
319 return 0;
320no_slave:
321 free_irq(MASTER_IRQ, &ixp_clock);
322no_master:
323 ptp_clock_unregister(ixp_clock.ptp_clock);
324 return -ENODEV;
325}
326
327module_init(ptp_ixp_init);
328module_exit(ptp_ixp_exit);
329
330MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
331MODULE_DESCRIPTION("PTP clock using the IXP46X timer");
332MODULE_LICENSE("GPL");
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
new file mode 100644
index 000000000000..4d5b5082c3b1
--- /dev/null
+++ b/drivers/ptp/ptp_private.h
@@ -0,0 +1,92 @@
1/*
2 * PTP 1588 clock support - private declarations for the core module.
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#ifndef _PTP_PRIVATE_H_
21#define _PTP_PRIVATE_H_
22
23#include <linux/cdev.h>
24#include <linux/device.h>
25#include <linux/mutex.h>
26#include <linux/posix-clock.h>
27#include <linux/ptp_clock.h>
28#include <linux/ptp_clock_kernel.h>
29#include <linux/time.h>
30
31#define PTP_MAX_TIMESTAMPS 128
32#define PTP_BUF_TIMESTAMPS 30
33
34struct timestamp_event_queue {
35 struct ptp_extts_event buf[PTP_MAX_TIMESTAMPS];
36 int head;
37 int tail;
38 spinlock_t lock;
39};
40
41struct ptp_clock {
42 struct posix_clock clock;
43 struct device *dev;
44 struct ptp_clock_info *info;
45 dev_t devid;
46 int index; /* index into clocks.map */
47 struct pps_device *pps_source;
48 struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
49 struct mutex tsevq_mux; /* one process at a time reading the fifo */
50 wait_queue_head_t tsev_wq;
51 int defunct; /* tells readers to go away when clock is being removed */
52};
53
54/*
55 * The function queue_cnt() is safe for readers to call without
56 * holding q->lock. Readers use this function to verify that the queue
57 * is nonempty before proceeding with a dequeue operation. The fact
58 * that a writer might concurrently increment the tail does not
59 * matter, since the queue remains nonempty nonetheless.
60 */
61static inline int queue_cnt(struct timestamp_event_queue *q)
62{
63 int cnt = q->tail - q->head;
64 return cnt < 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt;
65}
66
67/*
68 * see ptp_chardev.c
69 */
70
71long ptp_ioctl(struct posix_clock *pc,
72 unsigned int cmd, unsigned long arg);
73
74int ptp_open(struct posix_clock *pc, fmode_t fmode);
75
76ssize_t ptp_read(struct posix_clock *pc,
77 uint flags, char __user *buf, size_t cnt);
78
79uint ptp_poll(struct posix_clock *pc,
80 struct file *fp, poll_table *wait);
81
82/*
83 * see ptp_sysfs.c
84 */
85
86extern struct device_attribute ptp_dev_attrs[];
87
88int ptp_cleanup_sysfs(struct ptp_clock *ptp);
89
90int ptp_populate_sysfs(struct ptp_clock *ptp);
91
92#endif
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
new file mode 100644
index 000000000000..2f93926ac976
--- /dev/null
+++ b/drivers/ptp/ptp_sysfs.c
@@ -0,0 +1,230 @@
1/*
2 * PTP 1588 clock support - sysfs interface.
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/capability.h>
21
22#include "ptp_private.h"
23
24static ssize_t clock_name_show(struct device *dev,
25 struct device_attribute *attr, char *page)
26{
27 struct ptp_clock *ptp = dev_get_drvdata(dev);
28 return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
29}
30
31#define PTP_SHOW_INT(name) \
32static ssize_t name##_show(struct device *dev, \
33 struct device_attribute *attr, char *page) \
34{ \
35 struct ptp_clock *ptp = dev_get_drvdata(dev); \
36 return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->name); \
37}
38
39PTP_SHOW_INT(max_adj);
40PTP_SHOW_INT(n_alarm);
41PTP_SHOW_INT(n_ext_ts);
42PTP_SHOW_INT(n_per_out);
43PTP_SHOW_INT(pps);
44
45#define PTP_RO_ATTR(_var, _name) { \
46 .attr = { .name = __stringify(_name), .mode = 0444 }, \
47 .show = _var##_show, \
48}
49
50struct device_attribute ptp_dev_attrs[] = {
51 PTP_RO_ATTR(clock_name, clock_name),
52 PTP_RO_ATTR(max_adj, max_adjustment),
53 PTP_RO_ATTR(n_alarm, n_alarms),
54 PTP_RO_ATTR(n_ext_ts, n_external_timestamps),
55 PTP_RO_ATTR(n_per_out, n_periodic_outputs),
56 PTP_RO_ATTR(pps, pps_available),
57 __ATTR_NULL,
58};
59
60static ssize_t extts_enable_store(struct device *dev,
61 struct device_attribute *attr,
62 const char *buf, size_t count)
63{
64 struct ptp_clock *ptp = dev_get_drvdata(dev);
65 struct ptp_clock_info *ops = ptp->info;
66 struct ptp_clock_request req = { .type = PTP_CLK_REQ_EXTTS };
67 int cnt, enable;
68 int err = -EINVAL;
69
70 cnt = sscanf(buf, "%u %d", &req.extts.index, &enable);
71 if (cnt != 2)
72 goto out;
73 if (req.extts.index >= ops->n_ext_ts)
74 goto out;
75
76 err = ops->enable(ops, &req, enable ? 1 : 0);
77 if (err)
78 goto out;
79
80 return count;
81out:
82 return err;
83}
84
85static ssize_t extts_fifo_show(struct device *dev,
86 struct device_attribute *attr, char *page)
87{
88 struct ptp_clock *ptp = dev_get_drvdata(dev);
89 struct timestamp_event_queue *queue = &ptp->tsevq;
90 struct ptp_extts_event event;
91 unsigned long flags;
92 size_t qcnt;
93 int cnt = 0;
94
95 memset(&event, 0, sizeof(event));
96
97 if (mutex_lock_interruptible(&ptp->tsevq_mux))
98 return -ERESTARTSYS;
99
100 spin_lock_irqsave(&queue->lock, flags);
101 qcnt = queue_cnt(queue);
102 if (qcnt) {
103 event = queue->buf[queue->head];
104 queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
105 }
106 spin_unlock_irqrestore(&queue->lock, flags);
107
108 if (!qcnt)
109 goto out;
110
111 cnt = snprintf(page, PAGE_SIZE, "%u %lld %u\n",
112 event.index, event.t.sec, event.t.nsec);
113out:
114 mutex_unlock(&ptp->tsevq_mux);
115 return cnt;
116}
117
118static ssize_t period_store(struct device *dev,
119 struct device_attribute *attr,
120 const char *buf, size_t count)
121{
122 struct ptp_clock *ptp = dev_get_drvdata(dev);
123 struct ptp_clock_info *ops = ptp->info;
124 struct ptp_clock_request req = { .type = PTP_CLK_REQ_PEROUT };
125 int cnt, enable, err = -EINVAL;
126
127 cnt = sscanf(buf, "%u %lld %u %lld %u", &req.perout.index,
128 &req.perout.start.sec, &req.perout.start.nsec,
129 &req.perout.period.sec, &req.perout.period.nsec);
130 if (cnt != 5)
131 goto out;
132 if (req.perout.index >= ops->n_per_out)
133 goto out;
134
135 enable = req.perout.period.sec || req.perout.period.nsec;
136 err = ops->enable(ops, &req, enable);
137 if (err)
138 goto out;
139
140 return count;
141out:
142 return err;
143}
144
145static ssize_t pps_enable_store(struct device *dev,
146 struct device_attribute *attr,
147 const char *buf, size_t count)
148{
149 struct ptp_clock *ptp = dev_get_drvdata(dev);
150 struct ptp_clock_info *ops = ptp->info;
151 struct ptp_clock_request req = { .type = PTP_CLK_REQ_PPS };
152 int cnt, enable;
153 int err = -EINVAL;
154
155 if (!capable(CAP_SYS_TIME))
156 return -EPERM;
157
158 cnt = sscanf(buf, "%d", &enable);
159 if (cnt != 1)
160 goto out;
161
162 err = ops->enable(ops, &req, enable ? 1 : 0);
163 if (err)
164 goto out;
165
166 return count;
167out:
168 return err;
169}
170
171static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
172static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);
173static DEVICE_ATTR(period, 0220, NULL, period_store);
174static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
175
176int ptp_cleanup_sysfs(struct ptp_clock *ptp)
177{
178 struct device *dev = ptp->dev;
179 struct ptp_clock_info *info = ptp->info;
180
181 if (info->n_ext_ts) {
182 device_remove_file(dev, &dev_attr_extts_enable);
183 device_remove_file(dev, &dev_attr_fifo);
184 }
185 if (info->n_per_out)
186 device_remove_file(dev, &dev_attr_period);
187
188 if (info->pps)
189 device_remove_file(dev, &dev_attr_pps_enable);
190
191 return 0;
192}
193
194int ptp_populate_sysfs(struct ptp_clock *ptp)
195{
196 struct device *dev = ptp->dev;
197 struct ptp_clock_info *info = ptp->info;
198 int err;
199
200 if (info->n_ext_ts) {
201 err = device_create_file(dev, &dev_attr_extts_enable);
202 if (err)
203 goto out1;
204 err = device_create_file(dev, &dev_attr_fifo);
205 if (err)
206 goto out2;
207 }
208 if (info->n_per_out) {
209 err = device_create_file(dev, &dev_attr_period);
210 if (err)
211 goto out3;
212 }
213 if (info->pps) {
214 err = device_create_file(dev, &dev_attr_pps_enable);
215 if (err)
216 goto out4;
217 }
218 return 0;
219out4:
220 if (info->n_per_out)
221 device_remove_file(dev, &dev_attr_period);
222out3:
223 if (info->n_ext_ts)
224 device_remove_file(dev, &dev_attr_fifo);
225out2:
226 if (info->n_ext_ts)
227 device_remove_file(dev, &dev_attr_extts_enable);
228out1:
229 return err;
230}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index cb1ded2bd545..ccfedb4f3eb0 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -302,6 +302,7 @@ header-y += ppp-comp.h
302header-y += ppp_defs.h 302header-y += ppp_defs.h
303header-y += pps.h 303header-y += pps.h
304header-y += prctl.h 304header-y += prctl.h
305header-y += ptp_clock.h
305header-y += ptrace.h 306header-y += ptrace.h
306header-y += qnx4_fs.h 307header-y += qnx4_fs.h
307header-y += qnxtypes.h 308header-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 @@
25 25
26#include <linux/if_ether.h> 26#include <linux/if_ether.h>
27#include <linux/if_vlan.h> 27#include <linux/if_vlan.h>
28#include <linux/ip.h>
28#include <linux/filter.h> 29#include <linux/filter.h>
29#ifdef __KERNEL__ 30#ifdef __KERNEL__
30#include <linux/in.h> 31#include <linux/in.h>
@@ -58,6 +59,12 @@
58#define OFF_NEXT 6 59#define OFF_NEXT 6
59#define OFF_UDP_DST 2 60#define OFF_UDP_DST 2
60 61
62#define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */
63#define OFF_PTP_SEQUENCE_ID 30
64#define OFF_PTP_CONTROL 32 /* PTPv1 only */
65
66#define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2)
67
61#define IP6_HLEN 40 68#define IP6_HLEN 40
62#define UDP_HLEN 8 69#define UDP_HLEN 8
63 70
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 @@
1/*
2 * PTP 1588 clock support - user space interface
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef _PTP_CLOCK_H_
22#define _PTP_CLOCK_H_
23
24#include <linux/ioctl.h>
25#include <linux/types.h>
26
27/* PTP_xxx bits, for the flags field within the request structures. */
28#define PTP_ENABLE_FEATURE (1<<0)
29#define PTP_RISING_EDGE (1<<1)
30#define PTP_FALLING_EDGE (1<<2)
31
32/*
33 * struct ptp_clock_time - represents a time value
34 *
35 * The sign of the seconds field applies to the whole value. The
36 * nanoseconds field is always unsigned. The reserved field is
37 * included for sub-nanosecond resolution, should the demand for
38 * this ever appear.
39 *
40 */
41struct ptp_clock_time {
42 __s64 sec; /* seconds */
43 __u32 nsec; /* nanoseconds */
44 __u32 reserved;
45};
46
47struct ptp_clock_caps {
48 int max_adj; /* Maximum frequency adjustment in parts per billon. */
49 int n_alarm; /* Number of programmable alarms. */
50 int n_ext_ts; /* Number of external time stamp channels. */
51 int n_per_out; /* Number of programmable periodic signals. */
52 int pps; /* Whether the clock supports a PPS callback. */
53 int rsv[15]; /* Reserved for future use. */
54};
55
56struct ptp_extts_request {
57 unsigned int index; /* Which channel to configure. */
58 unsigned int flags; /* Bit field for PTP_xxx flags. */
59 unsigned int rsv[2]; /* Reserved for future use. */
60};
61
62struct ptp_perout_request {
63 struct ptp_clock_time start; /* Absolute start time. */
64 struct ptp_clock_time period; /* Desired period, zero means disable. */
65 unsigned int index; /* Which channel to configure. */
66 unsigned int flags; /* Reserved for future use. */
67 unsigned int rsv[4]; /* Reserved for future use. */
68};
69
70#define PTP_CLK_MAGIC '='
71
72#define PTP_CLOCK_GETCAPS _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps)
73#define PTP_EXTTS_REQUEST _IOW(PTP_CLK_MAGIC, 2, struct ptp_extts_request)
74#define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request)
75#define PTP_ENABLE_PPS _IOW(PTP_CLK_MAGIC, 4, int)
76
77struct ptp_extts_event {
78 struct ptp_clock_time t; /* Time event occured. */
79 unsigned int index; /* Which channel produced the event. */
80 unsigned int flags; /* Reserved for future use. */
81 unsigned int rsv[2]; /* Reserved for future use. */
82};
83
84#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 @@
1/*
2 * PTP 1588 clock support
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef _PTP_CLOCK_KERNEL_H_
22#define _PTP_CLOCK_KERNEL_H_
23
24#include <linux/ptp_clock.h>
25
26
27struct ptp_clock_request {
28 enum {
29 PTP_CLK_REQ_EXTTS,
30 PTP_CLK_REQ_PEROUT,
31 PTP_CLK_REQ_PPS,
32 } type;
33 union {
34 struct ptp_extts_request extts;
35 struct ptp_perout_request perout;
36 };
37};
38
39/**
40 * struct ptp_clock_info - decribes a PTP hardware clock
41 *
42 * @owner: The clock driver should set to THIS_MODULE.
43 * @name: A short name to identify the clock.
44 * @max_adj: The maximum possible frequency adjustment, in parts per billon.
45 * @n_alarm: The number of programmable alarms.
46 * @n_ext_ts: The number of external time stamp channels.
47 * @n_per_out: The number of programmable periodic signals.
48 * @pps: Indicates whether the clock supports a PPS callback.
49 *
50 * clock operations
51 *
52 * @adjfreq: Adjusts the frequency of the hardware clock.
53 * parameter delta: Desired period change in parts per billion.
54 *
55 * @adjtime: Shifts the time of the hardware clock.
56 * parameter delta: Desired change in nanoseconds.
57 *
58 * @gettime: Reads the current time from the hardware clock.
59 * parameter ts: Holds the result.
60 *
61 * @settime: Set the current time on the hardware clock.
62 * parameter ts: Time value to set.
63 *
64 * @enable: Request driver to enable or disable an ancillary feature.
65 * parameter request: Desired resource to enable or disable.
66 * parameter on: Caller passes one to enable or zero to disable.
67 *
68 * Drivers should embed their ptp_clock_info within a private
69 * structure, obtaining a reference to it using container_of().
70 *
71 * The callbacks must all return zero on success, non-zero otherwise.
72 */
73
74struct ptp_clock_info {
75 struct module *owner;
76 char name[16];
77 s32 max_adj;
78 int n_alarm;
79 int n_ext_ts;
80 int n_per_out;
81 int pps;
82 int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
83 int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
84 int (*gettime)(struct ptp_clock_info *ptp, struct timespec *ts);
85 int (*settime)(struct ptp_clock_info *ptp, const struct timespec *ts);
86 int (*enable)(struct ptp_clock_info *ptp,
87 struct ptp_clock_request *request, int on);
88};
89
90struct ptp_clock;
91
92/**
93 * ptp_clock_register() - register a PTP hardware clock driver
94 *
95 * @info: Structure describing the new clock.
96 */
97
98extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info);
99
100/**
101 * ptp_clock_unregister() - unregister a PTP hardware clock driver
102 *
103 * @ptp: The clock to remove from service.
104 */
105
106extern int ptp_clock_unregister(struct ptp_clock *ptp);
107
108
109enum ptp_clock_events {
110 PTP_CLOCK_ALARM,
111 PTP_CLOCK_EXTTS,
112 PTP_CLOCK_PPS,
113};
114
115/**
116 * struct ptp_clock_event - decribes a PTP hardware clock event
117 *
118 * @type: One of the ptp_clock_events enumeration values.
119 * @index: Identifies the source of the event.
120 * @timestamp: When the event occured.
121 */
122
123struct ptp_clock_event {
124 int type;
125 int index;
126 u64 timestamp;
127};
128
129/**
130 * ptp_clock_event() - notify the PTP layer about an event
131 *
132 * @ptp: The clock obtained from ptp_clock_register().
133 * @event: Message structure describing the event.
134 */
135
136extern void ptp_clock_event(struct ptp_clock *ptp,
137 struct ptp_clock_event *event);
138
139#endif