]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/ptp/ptp_qoriq.c
ptp: rework gianfar_ptp as QorIQ common PTP driver
[mirror_ubuntu-jammy-kernel.git] / drivers / ptp / ptp_qoriq.c
CommitLineData
c78275f3 1/*
ceefc71d 2 * PTP 1588 clock for Freescale QorIQ 1588 timer
c78275f3
RC
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 */
375d6a1b
JP
20
21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
c78275f3
RC
23#include <linux/device.h>
24#include <linux/hrtimer.h>
c78275f3
RC
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>
ceefc71d 32#include <linux/slab.h>
c78275f3
RC
33
34#include <linux/ptp_clock_kernel.h>
35
c78275f3 36/*
ceefc71d 37 * qoriq ptp registers
c78275f3
RC
38 * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
39 */
ceefc71d 40struct qoriq_ptp_registers {
c78275f3
RC
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 */
00a19e55 74#define FIPERST (1<<28) /* FIPER start indication */
c78275f3
RC
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
ceefc71d 129#define DRIVER "ptp_qoriq"
c78275f3 130#define DEFAULT_CKSEL 1
c78275f3 131#define N_EXT_TS 2
ceefc71d 132#define REG_SIZE sizeof(struct qoriq_ptp_registers)
c78275f3 133
ceefc71d
YL
134struct qoriq_ptp {
135 struct qoriq_ptp_registers __iomem *regs;
c78275f3
RC
136 spinlock_t lock; /* protects regs */
137 struct ptp_clock *clock;
138 struct ptp_clock_info caps;
139 struct resource *rsrc;
140 int irq;
ceefc71d 141 int phc_index;
c78275f3
RC
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
ceefc71d
YL
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
c78275f3
RC
165/*
166 * Register access functions
167 */
168
ceefc71d
YL
169/* Caller must hold qoriq_ptp->lock. */
170static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
c78275f3
RC
171{
172 u64 ns;
173 u32 lo, hi;
174
ceefc71d
YL
175 lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l);
176 hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h);
c78275f3
RC
177 ns = ((u64) hi) << 32;
178 ns |= lo;
179 return ns;
180}
181
ceefc71d
YL
182/* Caller must hold qoriq_ptp->lock. */
183static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
c78275f3
RC
184{
185 u32 hi = ns >> 32;
186 u32 lo = ns & 0xffffffff;
187
ceefc71d
YL
188 qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo);
189 qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi);
c78275f3
RC
190}
191
ceefc71d
YL
192/* Caller must hold qoriq_ptp->lock. */
193static void set_alarm(struct qoriq_ptp *qoriq_ptp)
c78275f3
RC
194{
195 u64 ns;
196 u32 lo, hi;
197
ceefc71d 198 ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL;
c78275f3 199 ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
ceefc71d 200 ns -= qoriq_ptp->tclk_period;
c78275f3
RC
201 hi = ns >> 32;
202 lo = ns & 0xffffffff;
ceefc71d
YL
203 qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo);
204 qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi);
c78275f3
RC
205}
206
ceefc71d
YL
207/* Caller must hold qoriq_ptp->lock. */
208static void set_fipers(struct qoriq_ptp *qoriq_ptp)
c78275f3 209{
ceefc71d
YL
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);
c78275f3
RC
213}
214
215/*
216 * Interrupt service routine
217 */
218
219static irqreturn_t isr(int irq, void *priv)
220{
ceefc71d 221 struct qoriq_ptp *qoriq_ptp = priv;
c78275f3
RC
222 struct ptp_clock_event event;
223 u64 ns;
224 u32 ack = 0, lo, hi, mask, val;
225
ceefc71d 226 val = qoriq_read(&qoriq_ptp->regs->tmr_tevent);
c78275f3
RC
227
228 if (val & ETS1) {
229 ack |= ETS1;
ceefc71d
YL
230 hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h);
231 lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l);
c78275f3
RC
232 event.type = PTP_CLOCK_EXTTS;
233 event.index = 0;
234 event.timestamp = ((u64) hi) << 32;
235 event.timestamp |= lo;
ceefc71d 236 ptp_clock_event(qoriq_ptp->clock, &event);
c78275f3
RC
237 }
238
239 if (val & ETS2) {
240 ack |= ETS2;
ceefc71d
YL
241 hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h);
242 lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l);
c78275f3
RC
243 event.type = PTP_CLOCK_EXTTS;
244 event.index = 1;
245 event.timestamp = ((u64) hi) << 32;
246 event.timestamp |= lo;
ceefc71d 247 ptp_clock_event(qoriq_ptp->clock, &event);
c78275f3
RC
248 }
249
250 if (val & ALM2) {
251 ack |= ALM2;
ceefc71d 252 if (qoriq_ptp->alarm_value) {
c78275f3
RC
253 event.type = PTP_CLOCK_ALARM;
254 event.index = 0;
ceefc71d
YL
255 event.timestamp = qoriq_ptp->alarm_value;
256 ptp_clock_event(qoriq_ptp->clock, &event);
c78275f3 257 }
ceefc71d
YL
258 if (qoriq_ptp->alarm_interval) {
259 ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval;
c78275f3
RC
260 hi = ns >> 32;
261 lo = ns & 0xffffffff;
ceefc71d
YL
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;
c78275f3 267 } else {
ceefc71d
YL
268 qoriq_write(&qoriq_ptp->regs->tmr_tevent, ALM2);
269 spin_lock(&qoriq_ptp->lock);
270 mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
c78275f3 271 mask &= ~ALM2EN;
ceefc71d
YL
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;
c78275f3
RC
276 }
277 }
278
279 if (val & PP1) {
280 ack |= PP1;
281 event.type = PTP_CLOCK_PPS;
ceefc71d 282 ptp_clock_event(qoriq_ptp->clock, &event);
c78275f3
RC
283 }
284
285 if (ack) {
ceefc71d 286 qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack);
c78275f3
RC
287 return IRQ_HANDLED;
288 } else
289 return IRQ_NONE;
290}
291
292/*
293 * PTP clock operations
294 */
295
ceefc71d 296static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
c78275f3 297{
42895116
UDB
298 u64 adj, diff;
299 u32 tmr_add;
c78275f3 300 int neg_adj = 0;
ceefc71d 301 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
c78275f3 302
42895116 303 if (scaled_ppm < 0) {
c78275f3 304 neg_adj = 1;
42895116 305 scaled_ppm = -scaled_ppm;
c78275f3 306 }
ceefc71d 307 tmr_add = qoriq_ptp->tmr_add;
c78275f3 308 adj = tmr_add;
42895116
UDB
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);
c78275f3
RC
316
317 tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
318
ceefc71d 319 qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add);
c78275f3
RC
320
321 return 0;
322}
323
ceefc71d 324static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta)
c78275f3
RC
325{
326 s64 now;
327 unsigned long flags;
ceefc71d 328 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
c78275f3 329
ceefc71d 330 spin_lock_irqsave(&qoriq_ptp->lock, flags);
c78275f3 331
ceefc71d 332 now = tmr_cnt_read(qoriq_ptp);
c78275f3 333 now += delta;
ceefc71d
YL
334 tmr_cnt_write(qoriq_ptp, now);
335 set_fipers(qoriq_ptp);
c78275f3 336
ceefc71d 337 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
c78275f3 338
c78275f3
RC
339 return 0;
340}
341
ceefc71d 342static int ptp_qoriq_gettime(struct ptp_clock_info *ptp,
d28fdf0f 343 struct timespec64 *ts)
c78275f3
RC
344{
345 u64 ns;
c78275f3 346 unsigned long flags;
ceefc71d 347 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
c78275f3 348
ceefc71d 349 spin_lock_irqsave(&qoriq_ptp->lock, flags);
c78275f3 350
ceefc71d 351 ns = tmr_cnt_read(qoriq_ptp);
c78275f3 352
ceefc71d 353 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
c78275f3 354
3359e7c2
RC
355 *ts = ns_to_timespec64(ns);
356
c78275f3
RC
357 return 0;
358}
359
ceefc71d 360static int ptp_qoriq_settime(struct ptp_clock_info *ptp,
d28fdf0f 361 const struct timespec64 *ts)
c78275f3
RC
362{
363 u64 ns;
364 unsigned long flags;
ceefc71d 365 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
c78275f3 366
3359e7c2 367 ns = timespec64_to_ns(ts);
c78275f3 368
ceefc71d 369 spin_lock_irqsave(&qoriq_ptp->lock, flags);
c78275f3 370
ceefc71d
YL
371 tmr_cnt_write(qoriq_ptp, ns);
372 set_fipers(qoriq_ptp);
c78275f3 373
ceefc71d 374 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
c78275f3
RC
375
376 return 0;
377}
378
ceefc71d 379static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
c78275f3
RC
380 struct ptp_clock_request *rq, int on)
381{
ceefc71d 382 struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
c78275f3
RC
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 }
ceefc71d
YL
398 spin_lock_irqsave(&qoriq_ptp->lock, flags);
399 mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
c78275f3
RC
400 if (on)
401 mask |= bit;
402 else
403 mask &= ~bit;
ceefc71d
YL
404 qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
405 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
c78275f3
RC
406 return 0;
407
408 case PTP_CLK_REQ_PPS:
ceefc71d
YL
409 spin_lock_irqsave(&qoriq_ptp->lock, flags);
410 mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
c78275f3
RC
411 if (on)
412 mask |= PP1EN;
413 else
414 mask &= ~PP1EN;
ceefc71d
YL
415 qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
416 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
c78275f3
RC
417 return 0;
418
419 default:
420 break;
421 }
422
423 return -EOPNOTSUPP;
424}
425
ceefc71d 426static const struct ptp_clock_info ptp_qoriq_caps = {
c78275f3 427 .owner = THIS_MODULE,
ceefc71d 428 .name = "qoriq ptp clock",
c78275f3 429 .max_adj = 512000,
cd4baaaa 430 .n_alarm = 0,
c78275f3
RC
431 .n_ext_ts = N_EXT_TS,
432 .n_per_out = 0,
4986b4f0 433 .n_pins = 0,
c78275f3 434 .pps = 1,
ceefc71d
YL
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,
c78275f3
RC
440};
441
ceefc71d 442static int qoriq_ptp_probe(struct platform_device *dev)
c78275f3
RC
443{
444 struct device_node *node = dev->dev.of_node;
ceefc71d 445 struct qoriq_ptp *qoriq_ptp;
d28fdf0f 446 struct timespec64 now;
c78275f3
RC
447 int err = -ENOMEM;
448 u32 tmr_ctrl;
449 unsigned long flags;
450
ceefc71d
YL
451 qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
452 if (!qoriq_ptp)
c78275f3
RC
453 goto no_memory;
454
455 err = -ENODEV;
456
ceefc71d 457 qoriq_ptp->caps = ptp_qoriq_caps;
e58f6f4f 458
ceefc71d
YL
459 if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel))
460 qoriq_ptp->cksel = DEFAULT_CKSEL;
c78275f3 461
c35ec779 462 if (of_property_read_u32(node,
ceefc71d 463 "fsl,tclk-period", &qoriq_ptp->tclk_period) ||
c35ec779 464 of_property_read_u32(node,
ceefc71d 465 "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) ||
c35ec779 466 of_property_read_u32(node,
ceefc71d 467 "fsl,tmr-add", &qoriq_ptp->tmr_add) ||
c35ec779 468 of_property_read_u32(node,
ceefc71d 469 "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) ||
c35ec779 470 of_property_read_u32(node,
ceefc71d 471 "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) ||
c35ec779 472 of_property_read_u32(node,
ceefc71d 473 "fsl,max-adj", &qoriq_ptp->caps.max_adj)) {
c78275f3
RC
474 pr_err("device tree node missing required elements\n");
475 goto no_node;
476 }
477
ceefc71d 478 qoriq_ptp->irq = platform_get_irq(dev, 0);
c78275f3 479
ceefc71d 480 if (qoriq_ptp->irq < 0) {
c78275f3
RC
481 pr_err("irq not in device tree\n");
482 goto no_node;
483 }
ceefc71d 484 if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) {
c78275f3
RC
485 pr_err("request_irq failed\n");
486 goto no_node;
487 }
488
ceefc71d
YL
489 qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
490 if (!qoriq_ptp->rsrc) {
c78275f3
RC
491 pr_err("no resource\n");
492 goto no_resource;
493 }
ceefc71d 494 if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) {
c78275f3
RC
495 pr_err("resource busy\n");
496 goto no_resource;
497 }
498
ceefc71d 499 spin_lock_init(&qoriq_ptp->lock);
c78275f3 500
ceefc71d
YL
501 qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start,
502 resource_size(qoriq_ptp->rsrc));
503 if (!qoriq_ptp->regs) {
c78275f3
RC
504 pr_err("ioremap ptp registers failed\n");
505 goto no_ioremap;
506 }
d28fdf0f 507 getnstimeofday64(&now);
ceefc71d 508 ptp_qoriq_settime(&qoriq_ptp->caps, &now);
c78275f3
RC
509
510 tmr_ctrl =
ceefc71d
YL
511 (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
512 (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT;
c78275f3 513
ceefc71d 514 spin_lock_irqsave(&qoriq_ptp->lock, flags);
c78275f3 515
ceefc71d
YL
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);
c78275f3 523
ceefc71d 524 spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
c78275f3 525
ceefc71d
YL
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);
c78275f3
RC
529 goto no_clock;
530 }
ceefc71d 531 qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock);
c78275f3 532
ceefc71d 533 platform_set_drvdata(dev, qoriq_ptp);
c78275f3
RC
534
535 return 0;
536
537no_clock:
ceefc71d 538 iounmap(qoriq_ptp->regs);
c78275f3 539no_ioremap:
ceefc71d 540 release_resource(qoriq_ptp->rsrc);
c78275f3 541no_resource:
ceefc71d 542 free_irq(qoriq_ptp->irq, qoriq_ptp);
c78275f3 543no_node:
ceefc71d 544 kfree(qoriq_ptp);
c78275f3
RC
545no_memory:
546 return err;
547}
548
ceefc71d 549static int qoriq_ptp_remove(struct platform_device *dev)
c78275f3 550{
ceefc71d 551 struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
c78275f3 552
ceefc71d
YL
553 qoriq_write(&qoriq_ptp->regs->tmr_temask, 0);
554 qoriq_write(&qoriq_ptp->regs->tmr_ctrl, 0);
c78275f3 555
ceefc71d
YL
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);
c78275f3
RC
561
562 return 0;
563}
564
94e5a2a8 565static const struct of_device_id match_table[] = {
c78275f3
RC
566 { .compatible = "fsl,etsec-ptp" },
567 {},
568};
23860063 569MODULE_DEVICE_TABLE(of, match_table);
c78275f3 570
ceefc71d 571static struct platform_driver qoriq_ptp_driver = {
c78275f3 572 .driver = {
ceefc71d 573 .name = "ptp_qoriq",
c78275f3 574 .of_match_table = match_table,
c78275f3 575 },
ceefc71d
YL
576 .probe = qoriq_ptp_probe,
577 .remove = qoriq_ptp_remove,
c78275f3
RC
578};
579
ceefc71d 580module_platform_driver(qoriq_ptp_driver);
c78275f3 581
c2ec3ff6 582MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
ceefc71d 583MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer");
c78275f3 584MODULE_LICENSE("GPL");