2 * TI Common Platform Time Sync
4 * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <linux/err.h>
22 #include <linux/hrtimer.h>
23 #include <linux/module.h>
24 #include <linux/net_tstamp.h>
25 #include <linux/ptp_classify.h>
26 #include <linux/time.h>
27 #include <linux/uaccess.h>
28 #include <linux/workqueue.h>
29 #include <linux/if_ether.h>
30 #include <linux/if_vlan.h>
34 #define CPTS_SKB_TX_WORK_TIMEOUT 1 /* jiffies */
36 struct cpts_skb_cb_data
{
40 #define cpts_read32(c, r) readl_relaxed(&c->reg->r)
41 #define cpts_write32(c, v, r) writel_relaxed(v, &c->reg->r)
43 static int cpts_match(struct sk_buff
*skb
, unsigned int ptp_class
,
44 u16 ts_seqid
, u8 ts_msgtype
);
46 static int event_expired(struct cpts_event
*event
)
48 return time_after(jiffies
, event
->tmo
);
51 static int event_type(struct cpts_event
*event
)
53 return (event
->high
>> EVENT_TYPE_SHIFT
) & EVENT_TYPE_MASK
;
56 static int cpts_fifo_pop(struct cpts
*cpts
, u32
*high
, u32
*low
)
58 u32 r
= cpts_read32(cpts
, intstat_raw
);
60 if (r
& TS_PEND_RAW
) {
61 *high
= cpts_read32(cpts
, event_high
);
62 *low
= cpts_read32(cpts
, event_low
);
63 cpts_write32(cpts
, EVENT_POP
, event_pop
);
69 static int cpts_purge_events(struct cpts
*cpts
)
71 struct list_head
*this, *next
;
72 struct cpts_event
*event
;
75 list_for_each_safe(this, next
, &cpts
->events
) {
76 event
= list_entry(this, struct cpts_event
, list
);
77 if (event_expired(event
)) {
78 list_del_init(&event
->list
);
79 list_add(&event
->list
, &cpts
->pool
);
85 pr_debug("cpts: event pool cleaned up %d\n", removed
);
86 return removed
? 0 : -1;
89 static bool cpts_match_tx_ts(struct cpts
*cpts
, struct cpts_event
*event
)
91 struct sk_buff
*skb
, *tmp
;
96 mtype
= (event
->high
>> MESSAGE_TYPE_SHIFT
) & MESSAGE_TYPE_MASK
;
97 seqid
= (event
->high
>> SEQUENCE_ID_SHIFT
) & SEQUENCE_ID_MASK
;
99 /* no need to grab txq.lock as access is always done under cpts->lock */
100 skb_queue_walk_safe(&cpts
->txq
, skb
, tmp
) {
101 struct skb_shared_hwtstamps ssh
;
102 unsigned int class = ptp_classify_raw(skb
);
103 struct cpts_skb_cb_data
*skb_cb
=
104 (struct cpts_skb_cb_data
*)skb
->cb
;
106 if (cpts_match(skb
, class, seqid
, mtype
)) {
107 u64 ns
= timecounter_cyc2time(&cpts
->tc
, event
->low
);
109 memset(&ssh
, 0, sizeof(ssh
));
110 ssh
.hwtstamp
= ns_to_ktime(ns
);
111 skb_tstamp_tx(skb
, &ssh
);
113 __skb_unlink(skb
, &cpts
->txq
);
114 dev_consume_skb_any(skb
);
115 dev_dbg(cpts
->dev
, "match tx timestamp mtype %u seqid %04x\n",
117 } else if (time_after(jiffies
, skb_cb
->tmo
)) {
118 /* timeout any expired skbs over 1s */
120 "expiring tx timestamp mtype %u seqid %04x\n",
122 __skb_unlink(skb
, &cpts
->txq
);
123 dev_consume_skb_any(skb
);
131 * Returns zero if matching event type was found.
133 static int cpts_fifo_read(struct cpts
*cpts
, int match
)
137 struct cpts_event
*event
;
139 for (i
= 0; i
< CPTS_FIFO_DEPTH
; i
++) {
140 if (cpts_fifo_pop(cpts
, &hi
, &lo
))
143 if (list_empty(&cpts
->pool
) && cpts_purge_events(cpts
)) {
144 pr_err("cpts: event pool empty\n");
148 event
= list_first_entry(&cpts
->pool
, struct cpts_event
, list
);
149 event
->tmo
= jiffies
+ 2;
152 type
= event_type(event
);
155 if (cpts_match_tx_ts(cpts
, event
)) {
156 /* if the new event matches an existing skb,
157 * then don't queue it
163 list_del_init(&event
->list
);
164 list_add_tail(&event
->list
, &cpts
->events
);
171 pr_err("cpts: unknown event type\n");
177 return type
== match
? 0 : -1;
180 static u64
cpts_systim_read(const struct cyclecounter
*cc
)
183 struct cpts_event
*event
;
184 struct list_head
*this, *next
;
185 struct cpts
*cpts
= container_of(cc
, struct cpts
, cc
);
187 cpts_write32(cpts
, TS_PUSH
, ts_push
);
188 if (cpts_fifo_read(cpts
, CPTS_EV_PUSH
))
189 pr_err("cpts: unable to obtain a time stamp\n");
191 list_for_each_safe(this, next
, &cpts
->events
) {
192 event
= list_entry(this, struct cpts_event
, list
);
193 if (event_type(event
) == CPTS_EV_PUSH
) {
194 list_del_init(&event
->list
);
195 list_add(&event
->list
, &cpts
->pool
);
204 /* PTP clock operations */
206 static int cpts_ptp_adjfreq(struct ptp_clock_info
*ptp
, s32 ppb
)
212 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
218 mult
= cpts
->cc_mult
;
221 diff
= div_u64(adj
, 1000000000ULL);
223 spin_lock_irqsave(&cpts
->lock
, flags
);
225 timecounter_read(&cpts
->tc
);
227 cpts
->cc
.mult
= neg_adj
? mult
- diff
: mult
+ diff
;
229 spin_unlock_irqrestore(&cpts
->lock
, flags
);
234 static int cpts_ptp_adjtime(struct ptp_clock_info
*ptp
, s64 delta
)
237 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
239 spin_lock_irqsave(&cpts
->lock
, flags
);
240 timecounter_adjtime(&cpts
->tc
, delta
);
241 spin_unlock_irqrestore(&cpts
->lock
, flags
);
246 static int cpts_ptp_gettime(struct ptp_clock_info
*ptp
, struct timespec64
*ts
)
250 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
252 spin_lock_irqsave(&cpts
->lock
, flags
);
253 ns
= timecounter_read(&cpts
->tc
);
254 spin_unlock_irqrestore(&cpts
->lock
, flags
);
256 *ts
= ns_to_timespec64(ns
);
261 static int cpts_ptp_settime(struct ptp_clock_info
*ptp
,
262 const struct timespec64
*ts
)
266 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
268 ns
= timespec64_to_ns(ts
);
270 spin_lock_irqsave(&cpts
->lock
, flags
);
271 timecounter_init(&cpts
->tc
, &cpts
->cc
, ns
);
272 spin_unlock_irqrestore(&cpts
->lock
, flags
);
277 static int cpts_ptp_enable(struct ptp_clock_info
*ptp
,
278 struct ptp_clock_request
*rq
, int on
)
283 static long cpts_overflow_check(struct ptp_clock_info
*ptp
)
285 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
286 unsigned long delay
= cpts
->ov_check_period
;
287 struct timespec64 ts
;
290 spin_lock_irqsave(&cpts
->lock
, flags
);
291 ts
= ns_to_timespec64(timecounter_read(&cpts
->tc
));
293 if (!skb_queue_empty(&cpts
->txq
))
294 delay
= CPTS_SKB_TX_WORK_TIMEOUT
;
295 spin_unlock_irqrestore(&cpts
->lock
, flags
);
297 pr_debug("cpts overflow check at %lld.%09lu\n", ts
.tv_sec
, ts
.tv_nsec
);
301 static const struct ptp_clock_info cpts_info
= {
302 .owner
= THIS_MODULE
,
303 .name
= "CTPS timer",
308 .adjfreq
= cpts_ptp_adjfreq
,
309 .adjtime
= cpts_ptp_adjtime
,
310 .gettime64
= cpts_ptp_gettime
,
311 .settime64
= cpts_ptp_settime
,
312 .enable
= cpts_ptp_enable
,
313 .do_aux_work
= cpts_overflow_check
,
316 static int cpts_match(struct sk_buff
*skb
, unsigned int ptp_class
,
317 u16 ts_seqid
, u8 ts_msgtype
)
320 unsigned int offset
= 0;
321 u8
*msgtype
, *data
= skb
->data
;
323 if (ptp_class
& PTP_CLASS_VLAN
)
326 switch (ptp_class
& PTP_CLASS_PMASK
) {
328 offset
+= ETH_HLEN
+ IPV4_HLEN(data
+ offset
) + UDP_HLEN
;
331 offset
+= ETH_HLEN
+ IP6_HLEN
+ UDP_HLEN
;
340 if (skb
->len
+ ETH_HLEN
< offset
+ OFF_PTP_SEQUENCE_ID
+ sizeof(*seqid
))
343 if (unlikely(ptp_class
& PTP_CLASS_V1
))
344 msgtype
= data
+ offset
+ OFF_PTP_CONTROL
;
346 msgtype
= data
+ offset
;
348 seqid
= (u16
*)(data
+ offset
+ OFF_PTP_SEQUENCE_ID
);
350 return (ts_msgtype
== (*msgtype
& 0xf) && ts_seqid
== ntohs(*seqid
));
353 static u64
cpts_find_ts(struct cpts
*cpts
, struct sk_buff
*skb
, int ev_type
)
356 struct cpts_event
*event
;
357 struct list_head
*this, *next
;
358 unsigned int class = ptp_classify_raw(skb
);
363 if (class == PTP_CLASS_NONE
)
366 spin_lock_irqsave(&cpts
->lock
, flags
);
367 cpts_fifo_read(cpts
, -1);
368 list_for_each_safe(this, next
, &cpts
->events
) {
369 event
= list_entry(this, struct cpts_event
, list
);
370 if (event_expired(event
)) {
371 list_del_init(&event
->list
);
372 list_add(&event
->list
, &cpts
->pool
);
375 mtype
= (event
->high
>> MESSAGE_TYPE_SHIFT
) & MESSAGE_TYPE_MASK
;
376 seqid
= (event
->high
>> SEQUENCE_ID_SHIFT
) & SEQUENCE_ID_MASK
;
377 if (ev_type
== event_type(event
) &&
378 cpts_match(skb
, class, seqid
, mtype
)) {
379 ns
= timecounter_cyc2time(&cpts
->tc
, event
->low
);
380 list_del_init(&event
->list
);
381 list_add(&event
->list
, &cpts
->pool
);
386 if (ev_type
== CPTS_EV_TX
&& !ns
) {
387 struct cpts_skb_cb_data
*skb_cb
=
388 (struct cpts_skb_cb_data
*)skb
->cb
;
389 /* Not found, add frame to queue for processing later.
390 * The periodic FIFO check will handle this.
393 /* get the timestamp for timeouts */
394 skb_cb
->tmo
= jiffies
+ msecs_to_jiffies(100);
395 __skb_queue_tail(&cpts
->txq
, skb
);
396 ptp_schedule_worker(cpts
->clock
, 0);
398 spin_unlock_irqrestore(&cpts
->lock
, flags
);
403 void cpts_rx_timestamp(struct cpts
*cpts
, struct sk_buff
*skb
)
406 struct skb_shared_hwtstamps
*ssh
;
408 if (!cpts
->rx_enable
)
410 ns
= cpts_find_ts(cpts
, skb
, CPTS_EV_RX
);
413 ssh
= skb_hwtstamps(skb
);
414 memset(ssh
, 0, sizeof(*ssh
));
415 ssh
->hwtstamp
= ns_to_ktime(ns
);
417 EXPORT_SYMBOL_GPL(cpts_rx_timestamp
);
419 void cpts_tx_timestamp(struct cpts
*cpts
, struct sk_buff
*skb
)
422 struct skb_shared_hwtstamps ssh
;
424 if (!(skb_shinfo(skb
)->tx_flags
& SKBTX_IN_PROGRESS
))
426 ns
= cpts_find_ts(cpts
, skb
, CPTS_EV_TX
);
429 memset(&ssh
, 0, sizeof(ssh
));
430 ssh
.hwtstamp
= ns_to_ktime(ns
);
431 skb_tstamp_tx(skb
, &ssh
);
433 EXPORT_SYMBOL_GPL(cpts_tx_timestamp
);
435 int cpts_register(struct cpts
*cpts
)
439 skb_queue_head_init(&cpts
->txq
);
440 INIT_LIST_HEAD(&cpts
->events
);
441 INIT_LIST_HEAD(&cpts
->pool
);
442 for (i
= 0; i
< CPTS_MAX_EVENTS
; i
++)
443 list_add(&cpts
->pool_data
[i
].list
, &cpts
->pool
);
445 clk_enable(cpts
->refclk
);
447 cpts_write32(cpts
, CPTS_EN
, control
);
448 cpts_write32(cpts
, TS_PEND_EN
, int_enable
);
450 timecounter_init(&cpts
->tc
, &cpts
->cc
, ktime_to_ns(ktime_get_real()));
452 cpts
->clock
= ptp_clock_register(&cpts
->info
, cpts
->dev
);
453 if (IS_ERR(cpts
->clock
)) {
454 err
= PTR_ERR(cpts
->clock
);
458 cpts
->phc_index
= ptp_clock_index(cpts
->clock
);
460 ptp_schedule_worker(cpts
->clock
, cpts
->ov_check_period
);
464 clk_disable(cpts
->refclk
);
467 EXPORT_SYMBOL_GPL(cpts_register
);
469 void cpts_unregister(struct cpts
*cpts
)
471 if (WARN_ON(!cpts
->clock
))
474 ptp_clock_unregister(cpts
->clock
);
477 cpts_write32(cpts
, 0, int_enable
);
478 cpts_write32(cpts
, 0, control
);
480 /* Drop all packet */
481 skb_queue_purge(&cpts
->txq
);
483 clk_disable(cpts
->refclk
);
485 EXPORT_SYMBOL_GPL(cpts_unregister
);
487 static void cpts_calc_mult_shift(struct cpts
*cpts
)
489 u64 frac
, maxsec
, ns
;
492 freq
= clk_get_rate(cpts
->refclk
);
494 /* Calc the maximum number of seconds which we can run before
497 maxsec
= cpts
->cc
.mask
;
498 do_div(maxsec
, freq
);
499 /* limit conversation rate to 10 sec as higher values will produce
500 * too small mult factors and so reduce the conversion accuracy
505 /* Calc overflow check period (maxsec / 2) */
506 cpts
->ov_check_period
= (HZ
* maxsec
) / 2;
507 dev_info(cpts
->dev
, "cpts: overflow check period %lu (jiffies)\n",
508 cpts
->ov_check_period
);
510 if (cpts
->cc
.mult
|| cpts
->cc
.shift
)
513 clocks_calc_mult_shift(&cpts
->cc
.mult
, &cpts
->cc
.shift
,
514 freq
, NSEC_PER_SEC
, maxsec
);
517 ns
= cyclecounter_cyc2ns(&cpts
->cc
, freq
, cpts
->cc
.mask
, &frac
);
520 "CPTS: ref_clk_freq:%u calc_mult:%u calc_shift:%u error:%lld nsec/sec\n",
521 freq
, cpts
->cc
.mult
, cpts
->cc
.shift
, (ns
- NSEC_PER_SEC
));
524 static int cpts_of_parse(struct cpts
*cpts
, struct device_node
*node
)
529 if (!of_property_read_u32(node
, "cpts_clock_mult", &prop
))
530 cpts
->cc
.mult
= prop
;
532 if (!of_property_read_u32(node
, "cpts_clock_shift", &prop
))
533 cpts
->cc
.shift
= prop
;
535 if ((cpts
->cc
.mult
&& !cpts
->cc
.shift
) ||
536 (!cpts
->cc
.mult
&& cpts
->cc
.shift
))
542 dev_err(cpts
->dev
, "CPTS: Missing property in the DT.\n");
546 struct cpts
*cpts_create(struct device
*dev
, void __iomem
*regs
,
547 struct device_node
*node
)
552 cpts
= devm_kzalloc(dev
, sizeof(*cpts
), GFP_KERNEL
);
554 return ERR_PTR(-ENOMEM
);
557 cpts
->reg
= (struct cpsw_cpts __iomem
*)regs
;
558 spin_lock_init(&cpts
->lock
);
560 ret
= cpts_of_parse(cpts
, node
);
564 cpts
->refclk
= devm_clk_get(dev
, "cpts");
565 if (IS_ERR(cpts
->refclk
)) {
566 dev_err(dev
, "Failed to get cpts refclk\n");
567 return ERR_PTR(PTR_ERR(cpts
->refclk
));
570 clk_prepare(cpts
->refclk
);
572 cpts
->cc
.read
= cpts_systim_read
;
573 cpts
->cc
.mask
= CLOCKSOURCE_MASK(32);
574 cpts
->info
= cpts_info
;
576 cpts_calc_mult_shift(cpts
);
577 /* save cc.mult original value as it can be modified
578 * by cpts_ptp_adjfreq().
580 cpts
->cc_mult
= cpts
->cc
.mult
;
584 EXPORT_SYMBOL_GPL(cpts_create
);
586 void cpts_release(struct cpts
*cpts
)
591 if (WARN_ON(!cpts
->refclk
))
594 clk_unprepare(cpts
->refclk
);
596 EXPORT_SYMBOL_GPL(cpts_release
);
598 MODULE_LICENSE("GPL v2");
599 MODULE_DESCRIPTION("TI CPTS driver");
600 MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");