summaryrefslogtreecommitdiffstats
path: root/drivers/ptp
diff options
context:
space:
mode:
authorYangbo Lu <yangbo.lu@nxp.com>2018-05-25 00:40:34 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-28 23:05:11 -0400
commitceefc71d4c055dab2bba2d2bfa6e7c2855154a24 (patch)
treea69ac99896fa84fa5218542b83d6d7ab8297490b /drivers/ptp
parentb1d2e4e03f92734ff524f96c4b2287133de7a4a3 (diff)
ptp: rework gianfar_ptp as QorIQ common PTP driver
gianfar_ptp was the PTP clock driver for 1588 timer module of Freescale QorIQ eTSEC (Enhanced Three-Speed Ethernet Controllers) platforms. Actually QorIQ DPAA (Data Path Acceleration Architecture) platforms is also using the same 1588 timer module in hardware. This patch is to rework gianfar_ptp as QorIQ common PTP driver to support both DPAA and eTSEC. Moved gianfar_ptp.c to drivers/ptp/, renamed it as ptp_qoriq.c, and renamed many variables. There were not any function changes. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/ptp')
-rw-r--r--drivers/ptp/Kconfig14
-rw-r--r--drivers/ptp/Makefile1
-rw-r--r--drivers/ptp/ptp_qoriq.c584
3 files changed, 592 insertions, 7 deletions
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index a21ad10d613c..474c988d2e95 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -41,19 +41,19 @@ config PTP_1588_CLOCK_DTE
41 To compile this driver as a module, choose M here: the module 41 To compile this driver as a module, choose M here: the module
42 will be called ptp_dte. 42 will be called ptp_dte.
43 43
44config PTP_1588_CLOCK_GIANFAR 44config PTP_1588_CLOCK_QORIQ
45 tristate "Freescale eTSEC as PTP clock" 45 tristate "Freescale QorIQ 1588 timer as PTP clock"
46 depends on GIANFAR 46 depends on GIANFAR
47 depends on PTP_1588_CLOCK 47 depends on PTP_1588_CLOCK
48 default y 48 default y
49 help 49 help
50 This driver adds support for using the eTSEC as a PTP 50 This driver adds support for using the Freescale QorIQ 1588
51 clock. This clock is only useful if your PTP programs are 51 timer as a PTP clock. This clock is only useful if your PTP
52 getting hardware time stamps on the PTP Ethernet packets 52 programs are getting hardware time stamps on the PTP Ethernet
53 using the SO_TIMESTAMPING API. 53 packets using the SO_TIMESTAMPING API.
54 54
55 To compile this driver as a module, choose M here: the module 55 To compile this driver as a module, choose M here: the module
56 will be called gianfar_ptp. 56 will be called ptp_qoriq.
57 57
58config PTP_1588_CLOCK_IXP46X 58config PTP_1588_CLOCK_IXP46X
59 tristate "Intel IXP46x as PTP clock" 59 tristate "Intel IXP46x as PTP clock"
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index fd28207f5379..19efa9cfa950 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o
9obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o 9obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
10obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o 10obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o
11obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o 11obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o
12obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp_qoriq.o
diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
new file mode 100644
index 000000000000..5110cce78fb5
--- /dev/null
+++ b/drivers/ptp/ptp_qoriq.c
@@ -0,0 +1,584 @@
1/*
2 * PTP 1588 clock for Freescale QorIQ 1588 timer
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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#include <linux/device.h>
24#include <linux/hrtimer.h>
25#include <linux/interrupt.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/of.h>
29#include <linux/of_platform.h>
30#include <linux/timex.h>
31#include <linux/io.h>
32#include <linux/slab.h>
33
34#include <linux/ptp_clock_kernel.h>
35
36/*
37 * qoriq ptp registers
38 * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
39 */
40struct qoriq_ptp_registers {
41 u32 tmr_ctrl; /* Timer control register */
42 u32 tmr_tevent; /* Timestamp event register */
43 u32 tmr_temask; /* Timer event mask register */
44 u32 tmr_pevent; /* Timestamp event register */
45 u32 tmr_pemask; /* Timer event mask register */
46 u32 tmr_stat; /* Timestamp status register */
47 u32 tmr_cnt_h; /* Timer counter high register */
48 u32 tmr_cnt_l; /* Timer counter low register */
49 u32 tmr_add; /* Timer drift compensation addend register */
50 u32 tmr_acc; /* Timer accumulator register */
51 u32 tmr_prsc; /* Timer prescale */
52 u8 res1[4];
53 u32 tmroff_h; /* Timer offset high */
54 u32 tmroff_l; /* Timer offset low */
55 u8 res2[8];
56 u32 tmr_alarm1_h; /* Timer alarm 1 high register */
57 u32 tmr_alarm1_l; /* Timer alarm 1 high register */
58 u32 tmr_alarm2_h; /* Timer alarm 2 high register */
59 u32 tmr_alarm2_l; /* Timer alarm 2 high register */
60 u8 res3[48];
61 u32 tmr_fiper1; /* Timer fixed period interval */
62 u32 tmr_fiper2; /* Timer fixed period interval */
63 u32 tmr_fiper3; /* Timer fixed period interval */
64 u8 res4[20];
65 u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */
66 u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */
67 u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */
68 u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */
69};
70
71/* Bit definitions for the TMR_CTRL register */
72#define ALM1P (1<<31) /* Alarm1 output polarity */
73#define ALM2P (1<<30) /* Alarm2 output polarity */
74#define FIPERST (1<<28) /* FIPER start indication */
75#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */
76#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */
77#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */
78#define TCLK_PERIOD_MASK (0x3ff)
79#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */
80#define FRD (1<<14) /* FIPER Realignment Disable */
81#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */
82#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */
83#define ETEP2 (1<<9) /* External trigger 2 edge polarity */
84#define ETEP1 (1<<8) /* External trigger 1 edge polarity */
85#define COPH (1<<7) /* Generated clock output phase. */
86#define CIPH (1<<6) /* External oscillator input clock phase */
87#define TMSR (1<<5) /* Timer soft reset. */
88#define BYP (1<<3) /* Bypass drift compensated clock */
89#define TE (1<<2) /* 1588 timer enable. */
90#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */
91#define CKSEL_MASK (0x3)
92
93/* Bit definitions for the TMR_TEVENT register */
94#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */
95#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */
96#define ALM2 (1<<17) /* Current time = alarm time register 2 */
97#define ALM1 (1<<16) /* Current time = alarm time register 1 */
98#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */
99#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */
100#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */
101
102/* Bit definitions for the TMR_TEMASK register */
103#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */
104#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */
105#define ALM2EN (1<<17) /* Timer ALM2 event enable */
106#define ALM1EN (1<<16) /* Timer ALM1 event enable */
107#define PP1EN (1<<7) /* Periodic pulse event 1 enable */
108#define PP2EN (1<<6) /* Periodic pulse event 2 enable */
109
110/* Bit definitions for the TMR_PEVENT register */
111#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */
112#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */
113#define RXP (1<<0) /* PTP frame has been received */
114
115/* Bit definitions for the TMR_PEMASK register */
116#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */
117#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */
118#define RXPEN (1<<0) /* Receive PTP packet event enable */
119
120/* Bit definitions for the TMR_STAT register */
121#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */
122#define STAT_VEC_MASK (0x3f)
123
124/* Bit definitions for the TMR_PRSC register */
125#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */
126#define PRSC_OCK_MASK (0xffff)
127
128
129#define DRIVER "ptp_qoriq"
130#define DEFAULT_CKSEL 1
131#define N_EXT_TS 2
132#define REG_SIZE sizeof(struct qoriq_ptp_registers)
133
134struct qoriq_ptp {
135 struct qoriq_ptp_registers __iomem *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 int phc_index;
142 u64 alarm_interval; /* for periodic alarm */
143 u64 alarm_value;
144 u32 tclk_period; /* nanoseconds */
145 u32 tmr_prsc;
146 u32 tmr_add;
147 u32 cksel;
148 u32 tmr_fiper1;
149 u32 tmr_fiper2;
150};
151
152static inline u32 qoriq_read(unsigned __iomem *addr)
153{
154 u32 val;
155
156 val = ioread32be(addr);
157 return val;
158}
159
160static inline void qoriq_write(unsigned __iomem *addr, u32 val)
161{
162 iowrite32be(val, addr);
163}
164
165/*
166 * Register access functions
167 */
168
169/* Caller must hold qoriq_ptp->lock. */
170static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
171{
172 u64 ns;
173 u32 lo, hi;
174
175 lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l);
176 hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h);
177 ns = ((u64) hi) << 32;
178 ns |= lo;
179 return ns;
180}
181
182/* Caller must hold qoriq_ptp->lock. */
183static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
184{
185 u32 hi = ns >> 32;
186 u32 lo = ns & 0xffffffff;
187
188 qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo);
189 qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi);
190}
191
192/* Caller must hold qoriq_ptp->lock. */
193static void set_alarm(struct qoriq_ptp *qoriq_ptp)
194{
195 u64 ns;
196 u32 lo, hi;
197
198 ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL;
199 ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
200 ns -= qoriq_ptp->tclk_period;
201 hi = ns >> 32;
202 lo = ns & 0xffffffff;
203 qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo);
204 qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi);
205}
206
207/* Caller must hold qoriq_ptp->lock. */
208static void set_fipers(struct qoriq_ptp *qoriq_ptp)
209{
210 set_alarm(qoriq_ptp);
211 qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
212 qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
213}
214
215/*
216 * Interrupt service routine
217 */
218
219static irqreturn_t isr(int irq, void *priv)
220{
221 struct qoriq_ptp *qoriq_ptp = priv;
222 struct ptp_clock_event event;
223 u64 ns;
224 u32 ack = 0, lo, hi, mask, val;
225
226 val = qoriq_read(&qoriq_ptp->regs->tmr_tevent);
227
228 if (val & ETS1) {
229 ack |= ETS1;
230 hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h);
231 lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l);
232 event.type = PTP_CLOCK_EXTTS;
233 event.index = 0;
234 event.timestamp = ((u64) hi) << 32;
235 event.timestamp |= lo;
236 ptp_clock_event(qoriq_ptp->clock, &event);
237 }
238
239 if (val & ETS2) {
240 ack |= ETS2;
241 hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h);
242 lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l);
243 event.type = PTP_CLOCK_EXTTS;
244 event.index = 1;
245 event.timestamp = ((u64) hi) << 32;
246 event.timestamp |= lo;
247 ptp_clock_event(qoriq_ptp->clock, &event);
248 }
249
250 if (val & ALM2) {
251 ack |= ALM2;
252 if (qoriq_ptp->alarm_value) {
253 event.type = PTP_CLOCK_ALARM;
254 event.index = 0;
255 event.timestamp = qoriq_ptp->alarm_value;
256 ptp_clock_event(qoriq_ptp->clock, &event);
257 }
258 if (qoriq_ptp->alarm_interval) {
259 ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval;
260 hi = ns >> 32;
261 lo = ns & 0xffffffff;
262 spin_lock(&qoriq_ptp->lock);
263 qoriq_write(&qoriq_ptp->regs->tmr_alarm2_l, lo);
264 qoriq_write(&qoriq_ptp->regs->tmr_alarm2_h, hi);
265 spin_unlock(&qoriq_ptp->lock);
266 qoriq_ptp->alarm_value = ns;
267 } else {
268 qoriq_write(&qoriq_ptp->regs->tmr_tevent, ALM2);
269 spin_lock(&qoriq_ptp->lock);
270 mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
271 mask &= ~ALM2EN;
272 qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
273 spin_unlock(&qoriq_ptp->lock);
274 qoriq_ptp->alarm_value = 0;
275 qoriq_ptp->alarm_interval = 0;
276 }
277 }
278
279 if (val & PP1) {
280 ack |= PP1;
281 event.type = PTP_CLOCK_PPS;
282 ptp_clock_event(qoriq_ptp->clock, &event);
283 }
284
285 if (ack) {
286 qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack);
287 return IRQ_HANDLED;
288 } else
289 return IRQ_NONE;
290}
291
292/*
293 * PTP clock operations
294 */
295
296static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
297{
298 u64 adj, diff;
299 u32 tmr_add;
300 int neg_adj = 0;
301 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
302
303 if (scaled_ppm < 0) {
304 neg_adj = 1;
305 scaled_ppm = -scaled_ppm;
306 }
307 tmr_add = qoriq_ptp->tmr_add;
308 adj = tmr_add;
309
310 /* calculate diff as adj*(scaled_ppm/65536)/1000000
311 * and round() to the nearest integer
312 */
313 adj *= scaled_ppm;
314 diff = div_u64(adj, 8000000);
315 diff = (diff >> 13) + ((diff >> 12) & 1);
316
317 tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
318
319 qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add);
320
321 return 0;
322}
323
324static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta)
325{
326 s64 now;
327 unsigned long flags;
328 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
329
330 spin_lock_irqsave(&qoriq_ptp->lock, flags);
331
332 now = tmr_cnt_read(qoriq_ptp);
333 now += delta;
334 tmr_cnt_write(qoriq_ptp, now);
335 set_fipers(qoriq_ptp);
336
337 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
338
339 return 0;
340}
341
342static int ptp_qoriq_gettime(struct ptp_clock_info *ptp,
343 struct timespec64 *ts)
344{
345 u64 ns;
346 unsigned long flags;
347 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
348
349 spin_lock_irqsave(&qoriq_ptp->lock, flags);
350
351 ns = tmr_cnt_read(qoriq_ptp);
352
353 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
354
355 *ts = ns_to_timespec64(ns);
356
357 return 0;
358}
359
360static int ptp_qoriq_settime(struct ptp_clock_info *ptp,
361 const struct timespec64 *ts)
362{
363 u64 ns;
364 unsigned long flags;
365 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
366
367 ns = timespec64_to_ns(ts);
368
369 spin_lock_irqsave(&qoriq_ptp->lock, flags);
370
371 tmr_cnt_write(qoriq_ptp, ns);
372 set_fipers(qoriq_ptp);
373
374 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
375
376 return 0;
377}
378
379static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
380 struct ptp_clock_request *rq, int on)
381{
382 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
383 unsigned long flags;
384 u32 bit, mask;
385
386 switch (rq->type) {
387 case PTP_CLK_REQ_EXTTS:
388 switch (rq->extts.index) {
389 case 0:
390 bit = ETS1EN;
391 break;
392 case 1:
393 bit = ETS2EN;
394 break;
395 default:
396 return -EINVAL;
397 }
398 spin_lock_irqsave(&qoriq_ptp->lock, flags);
399 mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
400 if (on)
401 mask |= bit;
402 else
403 mask &= ~bit;
404 qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
405 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
406 return 0;
407
408 case PTP_CLK_REQ_PPS:
409 spin_lock_irqsave(&qoriq_ptp->lock, flags);
410 mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
411 if (on)
412 mask |= PP1EN;
413 else
414 mask &= ~PP1EN;
415 qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
416 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
417 return 0;
418
419 default:
420 break;
421 }
422
423 return -EOPNOTSUPP;
424}
425
426static const struct ptp_clock_info ptp_qoriq_caps = {
427 .owner = THIS_MODULE,
428 .name = "qoriq ptp clock",
429 .max_adj = 512000,
430 .n_alarm = 0,
431 .n_ext_ts = N_EXT_TS,
432 .n_per_out = 0,
433 .n_pins = 0,
434 .pps = 1,
435 .adjfine = ptp_qoriq_adjfine,
436 .adjtime = ptp_qoriq_adjtime,
437 .gettime64 = ptp_qoriq_gettime,
438 .settime64 = ptp_qoriq_settime,
439 .enable = ptp_qoriq_enable,
440};
441
442static int qoriq_ptp_probe(struct platform_device *dev)
443{
444 struct device_node *node = dev->dev.of_node;
445 struct qoriq_ptp *qoriq_ptp;
446 struct timespec64 now;
447 int err = -ENOMEM;
448 u32 tmr_ctrl;
449 unsigned long flags;
450
451 qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
452 if (!qoriq_ptp)
453 goto no_memory;
454
455 err = -ENODEV;
456
457 qoriq_ptp->caps = ptp_qoriq_caps;
458
459 if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel))
460 qoriq_ptp->cksel = DEFAULT_CKSEL;
461
462 if (of_property_read_u32(node,
463 "fsl,tclk-period", &qoriq_ptp->tclk_period) ||
464 of_property_read_u32(node,
465 "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) ||
466 of_property_read_u32(node,
467 "fsl,tmr-add", &qoriq_ptp->tmr_add) ||
468 of_property_read_u32(node,
469 "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) ||
470 of_property_read_u32(node,
471 "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) ||
472 of_property_read_u32(node,
473 "fsl,max-adj", &qoriq_ptp->caps.max_adj)) {
474 pr_err("device tree node missing required elements\n");
475 goto no_node;
476 }
477
478 qoriq_ptp->irq = platform_get_irq(dev, 0);
479
480 if (qoriq_ptp->irq < 0) {
481 pr_err("irq not in device tree\n");
482 goto no_node;
483 }
484 if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) {
485 pr_err("request_irq failed\n");
486 goto no_node;
487 }
488
489 qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
490 if (!qoriq_ptp->rsrc) {
491 pr_err("no resource\n");
492 goto no_resource;
493 }
494 if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) {
495 pr_err("resource busy\n");
496 goto no_resource;
497 }
498
499 spin_lock_init(&qoriq_ptp->lock);
500
501 qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start,
502 resource_size(qoriq_ptp->rsrc));
503 if (!qoriq_ptp->regs) {
504 pr_err("ioremap ptp registers failed\n");
505 goto no_ioremap;
506 }
507 getnstimeofday64(&now);
508 ptp_qoriq_settime(&qoriq_ptp->caps, &now);
509
510 tmr_ctrl =
511 (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
512 (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT;
513
514 spin_lock_irqsave(&qoriq_ptp->lock, flags);
515
516 qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl);
517 qoriq_write(&qoriq_ptp->regs->tmr_add, qoriq_ptp->tmr_add);
518 qoriq_write(&qoriq_ptp->regs->tmr_prsc, qoriq_ptp->tmr_prsc);
519 qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
520 qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
521 set_alarm(qoriq_ptp);
522 qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
523
524 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
525
526 qoriq_ptp->clock = ptp_clock_register(&qoriq_ptp->caps, &dev->dev);
527 if (IS_ERR(qoriq_ptp->clock)) {
528 err = PTR_ERR(qoriq_ptp->clock);
529 goto no_clock;
530 }
531 qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock);
532
533 platform_set_drvdata(dev, qoriq_ptp);
534
535 return 0;
536
537no_clock:
538 iounmap(qoriq_ptp->regs);
539no_ioremap:
540 release_resource(qoriq_ptp->rsrc);
541no_resource:
542 free_irq(qoriq_ptp->irq, qoriq_ptp);
543no_node:
544 kfree(qoriq_ptp);
545no_memory:
546 return err;
547}
548
549static int qoriq_ptp_remove(struct platform_device *dev)
550{
551 struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
552
553 qoriq_write(&qoriq_ptp->regs->tmr_temask, 0);
554 qoriq_write(&qoriq_ptp->regs->tmr_ctrl, 0);
555
556 ptp_clock_unregister(qoriq_ptp->clock);
557 iounmap(qoriq_ptp->regs);
558 release_resource(qoriq_ptp->rsrc);
559 free_irq(qoriq_ptp->irq, qoriq_ptp);
560 kfree(qoriq_ptp);
561
562 return 0;
563}
564
565static const struct of_device_id match_table[] = {
566 { .compatible = "fsl,etsec-ptp" },
567 {},
568};
569MODULE_DEVICE_TABLE(of, match_table);
570
571static struct platform_driver qoriq_ptp_driver = {
572 .driver = {
573 .name = "ptp_qoriq",
574 .of_match_table = match_table,
575 },
576 .probe = qoriq_ptp_probe,
577 .remove = qoriq_ptp_remove,
578};
579
580module_platform_driver(qoriq_ptp_driver);
581
582MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
583MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer");
584MODULE_LICENSE("GPL");