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>
34 static struct sock_filter ptp_filter
[] = {
38 #define cpts_read32(c, r) __raw_readl(&c->reg->r)
39 #define cpts_write32(c, v, r) __raw_writel(v, &c->reg->r)
41 static int event_expired(struct cpts_event
*event
)
43 return time_after(jiffies
, event
->tmo
);
46 static int event_type(struct cpts_event
*event
)
48 return (event
->high
>> EVENT_TYPE_SHIFT
) & EVENT_TYPE_MASK
;
51 static int cpts_fifo_pop(struct cpts
*cpts
, u32
*high
, u32
*low
)
53 u32 r
= cpts_read32(cpts
, intstat_raw
);
55 if (r
& TS_PEND_RAW
) {
56 *high
= cpts_read32(cpts
, event_high
);
57 *low
= cpts_read32(cpts
, event_low
);
58 cpts_write32(cpts
, EVENT_POP
, event_pop
);
65 * Returns zero if matching event type was found.
67 static int cpts_fifo_read(struct cpts
*cpts
, int match
)
71 struct cpts_event
*event
;
73 for (i
= 0; i
< CPTS_FIFO_DEPTH
; i
++) {
74 if (cpts_fifo_pop(cpts
, &hi
, &lo
))
76 if (list_empty(&cpts
->pool
)) {
77 pr_err("cpts: event pool is empty\n");
80 event
= list_first_entry(&cpts
->pool
, struct cpts_event
, list
);
81 event
->tmo
= jiffies
+ 2;
84 type
= event_type(event
);
89 list_del_init(&event
->list
);
90 list_add_tail(&event
->list
, &cpts
->events
);
97 pr_err("cpts: unknown event type\n");
103 return type
== match
? 0 : -1;
106 static cycle_t
cpts_systim_read(const struct cyclecounter
*cc
)
109 struct cpts_event
*event
;
110 struct list_head
*this, *next
;
111 struct cpts
*cpts
= container_of(cc
, struct cpts
, cc
);
113 cpts_write32(cpts
, TS_PUSH
, ts_push
);
114 if (cpts_fifo_read(cpts
, CPTS_EV_PUSH
))
115 pr_err("cpts: unable to obtain a time stamp\n");
117 list_for_each_safe(this, next
, &cpts
->events
) {
118 event
= list_entry(this, struct cpts_event
, list
);
119 if (event_type(event
) == CPTS_EV_PUSH
) {
120 list_del_init(&event
->list
);
121 list_add(&event
->list
, &cpts
->pool
);
130 /* PTP clock operations */
132 static int cpts_ptp_adjfreq(struct ptp_clock_info
*ptp
, s32 ppb
)
138 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
144 mult
= cpts
->cc_mult
;
147 diff
= div_u64(adj
, 1000000000ULL);
149 spin_lock_irqsave(&cpts
->lock
, flags
);
151 timecounter_read(&cpts
->tc
);
153 cpts
->cc
.mult
= neg_adj
? mult
- diff
: mult
+ diff
;
155 spin_unlock_irqrestore(&cpts
->lock
, flags
);
160 static int cpts_ptp_adjtime(struct ptp_clock_info
*ptp
, s64 delta
)
164 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
166 spin_lock_irqsave(&cpts
->lock
, flags
);
167 now
= timecounter_read(&cpts
->tc
);
169 timecounter_init(&cpts
->tc
, &cpts
->cc
, now
);
170 spin_unlock_irqrestore(&cpts
->lock
, flags
);
175 static int cpts_ptp_gettime(struct ptp_clock_info
*ptp
, struct timespec
*ts
)
180 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
182 spin_lock_irqsave(&cpts
->lock
, flags
);
183 ns
= timecounter_read(&cpts
->tc
);
184 spin_unlock_irqrestore(&cpts
->lock
, flags
);
186 ts
->tv_sec
= div_u64_rem(ns
, 1000000000, &remainder
);
187 ts
->tv_nsec
= remainder
;
192 static int cpts_ptp_settime(struct ptp_clock_info
*ptp
,
193 const struct timespec
*ts
)
197 struct cpts
*cpts
= container_of(ptp
, struct cpts
, info
);
199 ns
= ts
->tv_sec
* 1000000000ULL;
202 spin_lock_irqsave(&cpts
->lock
, flags
);
203 timecounter_init(&cpts
->tc
, &cpts
->cc
, ns
);
204 spin_unlock_irqrestore(&cpts
->lock
, flags
);
209 static int cpts_ptp_enable(struct ptp_clock_info
*ptp
,
210 struct ptp_clock_request
*rq
, int on
)
215 static struct ptp_clock_info cpts_info
= {
216 .owner
= THIS_MODULE
,
217 .name
= "CTPS timer",
221 .adjfreq
= cpts_ptp_adjfreq
,
222 .adjtime
= cpts_ptp_adjtime
,
223 .gettime
= cpts_ptp_gettime
,
224 .settime
= cpts_ptp_settime
,
225 .enable
= cpts_ptp_enable
,
228 static void cpts_overflow_check(struct work_struct
*work
)
231 struct cpts
*cpts
= container_of(work
, struct cpts
, overflow_work
.work
);
233 cpts_write32(cpts
, CPTS_EN
, control
);
234 cpts_write32(cpts
, TS_PEND_EN
, int_enable
);
235 cpts_ptp_gettime(&cpts
->info
, &ts
);
236 pr_debug("cpts overflow check at %ld.%09lu\n", ts
.tv_sec
, ts
.tv_nsec
);
237 schedule_delayed_work(&cpts
->overflow_work
, CPTS_OVERFLOW_PERIOD
);
240 #define CPTS_REF_CLOCK_NAME "cpsw_cpts_rft_clk"
242 static void cpts_clk_init(struct cpts
*cpts
)
244 cpts
->refclk
= clk_get(NULL
, CPTS_REF_CLOCK_NAME
);
245 if (IS_ERR(cpts
->refclk
)) {
246 pr_err("Failed to clk_get %s\n", CPTS_REF_CLOCK_NAME
);
250 clk_prepare_enable(cpts
->refclk
);
253 static void cpts_clk_release(struct cpts
*cpts
)
255 clk_disable(cpts
->refclk
);
256 clk_put(cpts
->refclk
);
259 static int cpts_match(struct sk_buff
*skb
, unsigned int ptp_class
,
260 u16 ts_seqid
, u8 ts_msgtype
)
264 u8
*msgtype
, *data
= skb
->data
;
267 case PTP_CLASS_V1_IPV4
:
268 case PTP_CLASS_V2_IPV4
:
269 offset
= ETH_HLEN
+ IPV4_HLEN(data
) + UDP_HLEN
;
271 case PTP_CLASS_V1_IPV6
:
272 case PTP_CLASS_V2_IPV6
:
275 case PTP_CLASS_V2_L2
:
278 case PTP_CLASS_V2_VLAN
:
279 offset
= ETH_HLEN
+ VLAN_HLEN
;
285 if (skb
->len
+ ETH_HLEN
< offset
+ OFF_PTP_SEQUENCE_ID
+ sizeof(*seqid
))
288 if (unlikely(ptp_class
& PTP_CLASS_V1
))
289 msgtype
= data
+ offset
+ OFF_PTP_CONTROL
;
291 msgtype
= data
+ offset
;
293 seqid
= (u16
*)(data
+ offset
+ OFF_PTP_SEQUENCE_ID
);
295 return (ts_msgtype
== (*msgtype
& 0xf) && ts_seqid
== ntohs(*seqid
));
298 static u64
cpts_find_ts(struct cpts
*cpts
, struct sk_buff
*skb
, int ev_type
)
301 struct cpts_event
*event
;
302 struct list_head
*this, *next
;
303 unsigned int class = sk_run_filter(skb
, ptp_filter
);
308 if (class == PTP_CLASS_NONE
)
311 spin_lock_irqsave(&cpts
->lock
, flags
);
312 cpts_fifo_read(cpts
, CPTS_EV_PUSH
);
313 list_for_each_safe(this, next
, &cpts
->events
) {
314 event
= list_entry(this, struct cpts_event
, list
);
315 if (event_expired(event
)) {
316 list_del_init(&event
->list
);
317 list_add(&event
->list
, &cpts
->pool
);
320 mtype
= (event
->high
>> MESSAGE_TYPE_SHIFT
) & MESSAGE_TYPE_MASK
;
321 seqid
= (event
->high
>> SEQUENCE_ID_SHIFT
) & SEQUENCE_ID_MASK
;
322 if (ev_type
== event_type(event
) &&
323 cpts_match(skb
, class, seqid
, mtype
)) {
324 ns
= timecounter_cyc2time(&cpts
->tc
, event
->low
);
325 list_del_init(&event
->list
);
326 list_add(&event
->list
, &cpts
->pool
);
330 spin_unlock_irqrestore(&cpts
->lock
, flags
);
335 void cpts_rx_timestamp(struct cpts
*cpts
, struct sk_buff
*skb
)
338 struct skb_shared_hwtstamps
*ssh
;
340 if (!cpts
->rx_enable
)
342 ns
= cpts_find_ts(cpts
, skb
, CPTS_EV_RX
);
345 ssh
= skb_hwtstamps(skb
);
346 memset(ssh
, 0, sizeof(*ssh
));
347 ssh
->hwtstamp
= ns_to_ktime(ns
);
350 void cpts_tx_timestamp(struct cpts
*cpts
, struct sk_buff
*skb
)
353 struct skb_shared_hwtstamps ssh
;
355 if (!(skb_shinfo(skb
)->tx_flags
& SKBTX_IN_PROGRESS
))
357 ns
= cpts_find_ts(cpts
, skb
, CPTS_EV_TX
);
360 memset(&ssh
, 0, sizeof(ssh
));
361 ssh
.hwtstamp
= ns_to_ktime(ns
);
362 skb_tstamp_tx(skb
, &ssh
);
365 #endif /*CONFIG_TI_CPTS*/
367 int cpts_register(struct device
*dev
, struct cpts
*cpts
,
370 #ifdef CONFIG_TI_CPTS
374 if (ptp_filter_init(ptp_filter
, ARRAY_SIZE(ptp_filter
))) {
375 pr_err("cpts: bad ptp filter\n");
378 cpts
->info
= cpts_info
;
379 cpts
->clock
= ptp_clock_register(&cpts
->info
, dev
);
380 if (IS_ERR(cpts
->clock
)) {
381 err
= PTR_ERR(cpts
->clock
);
385 spin_lock_init(&cpts
->lock
);
387 cpts
->cc
.read
= cpts_systim_read
;
388 cpts
->cc
.mask
= CLOCKSOURCE_MASK(32);
389 cpts
->cc_mult
= mult
;
390 cpts
->cc
.mult
= mult
;
391 cpts
->cc
.shift
= shift
;
393 INIT_LIST_HEAD(&cpts
->events
);
394 INIT_LIST_HEAD(&cpts
->pool
);
395 for (i
= 0; i
< CPTS_MAX_EVENTS
; i
++)
396 list_add(&cpts
->pool_data
[i
].list
, &cpts
->pool
);
399 cpts_write32(cpts
, CPTS_EN
, control
);
400 cpts_write32(cpts
, TS_PEND_EN
, int_enable
);
402 spin_lock_irqsave(&cpts
->lock
, flags
);
403 timecounter_init(&cpts
->tc
, &cpts
->cc
, ktime_to_ns(ktime_get_real()));
404 spin_unlock_irqrestore(&cpts
->lock
, flags
);
406 INIT_DELAYED_WORK(&cpts
->overflow_work
, cpts_overflow_check
);
407 schedule_delayed_work(&cpts
->overflow_work
, CPTS_OVERFLOW_PERIOD
);
409 cpts
->phc_index
= ptp_clock_index(cpts
->clock
);
414 void cpts_unregister(struct cpts
*cpts
)
416 #ifdef CONFIG_TI_CPTS
418 ptp_clock_unregister(cpts
->clock
);
419 cancel_delayed_work_sync(&cpts
->overflow_work
);
422 cpts_clk_release(cpts
);