16b1baefeSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c1167ceeSYang Shen /*
3ab91f0a9SRafal Ozieblo  * 1588 PTP support for Cadence GEM device.
4ab91f0a9SRafal Ozieblo  *
55d75c043SAlexander A. Klimov  * Copyright (C) 2017 Cadence Design Systems - https://www.cadence.com
6ab91f0a9SRafal Ozieblo  *
7ab91f0a9SRafal Ozieblo  * Authors: Rafal Ozieblo <rafalo@cadence.com>
8ab91f0a9SRafal Ozieblo  *          Bartosz Folta <bfolta@cadence.com>
9ab91f0a9SRafal Ozieblo  */
10ab91f0a9SRafal Ozieblo #include <linux/kernel.h>
11ab91f0a9SRafal Ozieblo #include <linux/types.h>
12ab91f0a9SRafal Ozieblo #include <linux/clk.h>
13ab91f0a9SRafal Ozieblo #include <linux/device.h>
14ab91f0a9SRafal Ozieblo #include <linux/etherdevice.h>
15ab91f0a9SRafal Ozieblo #include <linux/platform_device.h>
16ab91f0a9SRafal Ozieblo #include <linux/time64.h>
17ab91f0a9SRafal Ozieblo #include <linux/ptp_classify.h>
18ab91f0a9SRafal Ozieblo #include <linux/if_ether.h>
19ab91f0a9SRafal Ozieblo #include <linux/if_vlan.h>
20ab91f0a9SRafal Ozieblo #include <linux/net_tstamp.h>
21ab91f0a9SRafal Ozieblo #include <linux/circ_buf.h>
22ab91f0a9SRafal Ozieblo #include <linux/spinlock.h>
23ab91f0a9SRafal Ozieblo 
24ab91f0a9SRafal Ozieblo #include "macb.h"
25ab91f0a9SRafal Ozieblo 
26ab91f0a9SRafal Ozieblo #define  GEM_PTP_TIMER_NAME "gem-ptp-timer"
27ab91f0a9SRafal Ozieblo 
macb_ptp_desc(struct macb * bp,struct macb_dma_desc * desc)28ab91f0a9SRafal Ozieblo static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp,
29ab91f0a9SRafal Ozieblo 					       struct macb_dma_desc *desc)
30ab91f0a9SRafal Ozieblo {
31ab91f0a9SRafal Ozieblo 	if (bp->hw_dma_cap == HW_DMA_CAP_PTP)
32ab91f0a9SRafal Ozieblo 		return (struct macb_dma_desc_ptp *)
33ab91f0a9SRafal Ozieblo 				((u8 *)desc + sizeof(struct macb_dma_desc));
34ab91f0a9SRafal Ozieblo 	if (bp->hw_dma_cap == HW_DMA_CAP_64B_PTP)
35ab91f0a9SRafal Ozieblo 		return (struct macb_dma_desc_ptp *)
36ab91f0a9SRafal Ozieblo 				((u8 *)desc + sizeof(struct macb_dma_desc)
37ab91f0a9SRafal Ozieblo 				+ sizeof(struct macb_dma_desc_64));
38ab91f0a9SRafal Ozieblo 	return NULL;
39ab91f0a9SRafal Ozieblo }
40ab91f0a9SRafal Ozieblo 
gem_tsu_get_time(struct ptp_clock_info * ptp,struct timespec64 * ts,struct ptp_system_timestamp * sts)41e51bb5c2SLars-Peter Clausen static int gem_tsu_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts,
42e51bb5c2SLars-Peter Clausen 			    struct ptp_system_timestamp *sts)
43ab91f0a9SRafal Ozieblo {
44ab91f0a9SRafal Ozieblo 	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
45ab91f0a9SRafal Ozieblo 	unsigned long flags;
46ab91f0a9SRafal Ozieblo 	long first, second;
47ab91f0a9SRafal Ozieblo 	u32 secl, sech;
48ab91f0a9SRafal Ozieblo 
49ab91f0a9SRafal Ozieblo 	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
50e51bb5c2SLars-Peter Clausen 	ptp_read_system_prets(sts);
51ab91f0a9SRafal Ozieblo 	first = gem_readl(bp, TN);
52e51bb5c2SLars-Peter Clausen 	ptp_read_system_postts(sts);
53ab91f0a9SRafal Ozieblo 	secl = gem_readl(bp, TSL);
54ab91f0a9SRafal Ozieblo 	sech = gem_readl(bp, TSH);
55ab91f0a9SRafal Ozieblo 	second = gem_readl(bp, TN);
56ab91f0a9SRafal Ozieblo 
57ab91f0a9SRafal Ozieblo 	/* test for nsec rollover */
58ab91f0a9SRafal Ozieblo 	if (first > second) {
59ab91f0a9SRafal Ozieblo 		/* if so, use later read & re-read seconds
60ab91f0a9SRafal Ozieblo 		 * (assume all done within 1s)
61ab91f0a9SRafal Ozieblo 		 */
62e51bb5c2SLars-Peter Clausen 		ptp_read_system_prets(sts);
63ab91f0a9SRafal Ozieblo 		ts->tv_nsec = gem_readl(bp, TN);
64e51bb5c2SLars-Peter Clausen 		ptp_read_system_postts(sts);
65ab91f0a9SRafal Ozieblo 		secl = gem_readl(bp, TSL);
66ab91f0a9SRafal Ozieblo 		sech = gem_readl(bp, TSH);
67ab91f0a9SRafal Ozieblo 	} else {
68ab91f0a9SRafal Ozieblo 		ts->tv_nsec = first;
69ab91f0a9SRafal Ozieblo 	}
70ab91f0a9SRafal Ozieblo 
71ab91f0a9SRafal Ozieblo 	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
72ab91f0a9SRafal Ozieblo 	ts->tv_sec = (((u64)sech << GEM_TSL_SIZE) | secl)
73ab91f0a9SRafal Ozieblo 			& TSU_SEC_MAX_VAL;
74ab91f0a9SRafal Ozieblo 	return 0;
75ab91f0a9SRafal Ozieblo }
76ab91f0a9SRafal Ozieblo 
gem_tsu_set_time(struct ptp_clock_info * ptp,const struct timespec64 * ts)77ab91f0a9SRafal Ozieblo static int gem_tsu_set_time(struct ptp_clock_info *ptp,
78ab91f0a9SRafal Ozieblo 			    const struct timespec64 *ts)
79ab91f0a9SRafal Ozieblo {
80ab91f0a9SRafal Ozieblo 	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
81ab91f0a9SRafal Ozieblo 	unsigned long flags;
82ab91f0a9SRafal Ozieblo 	u32 ns, sech, secl;
83ab91f0a9SRafal Ozieblo 
84ab91f0a9SRafal Ozieblo 	secl = (u32)ts->tv_sec;
85ab91f0a9SRafal Ozieblo 	sech = (ts->tv_sec >> GEM_TSL_SIZE) & ((1 << GEM_TSH_SIZE) - 1);
86ab91f0a9SRafal Ozieblo 	ns = ts->tv_nsec;
87ab91f0a9SRafal Ozieblo 
88ab91f0a9SRafal Ozieblo 	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
89ab91f0a9SRafal Ozieblo 
90ab91f0a9SRafal Ozieblo 	/* TSH doesn't latch the time and no atomicity! */
91ab91f0a9SRafal Ozieblo 	gem_writel(bp, TN, 0); /* clear to avoid overflow */
92ab91f0a9SRafal Ozieblo 	gem_writel(bp, TSH, sech);
93ab91f0a9SRafal Ozieblo 	/* write lower bits 2nd, for synchronized secs update */
94ab91f0a9SRafal Ozieblo 	gem_writel(bp, TSL, secl);
95ab91f0a9SRafal Ozieblo 	gem_writel(bp, TN, ns);
96ab91f0a9SRafal Ozieblo 
97ab91f0a9SRafal Ozieblo 	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
98ab91f0a9SRafal Ozieblo 
99ab91f0a9SRafal Ozieblo 	return 0;
100ab91f0a9SRafal Ozieblo }
101ab91f0a9SRafal Ozieblo 
gem_tsu_incr_set(struct macb * bp,struct tsu_incr * incr_spec)102ab91f0a9SRafal Ozieblo static int gem_tsu_incr_set(struct macb *bp, struct tsu_incr *incr_spec)
103ab91f0a9SRafal Ozieblo {
104ab91f0a9SRafal Ozieblo 	unsigned long flags;
105ab91f0a9SRafal Ozieblo 
106ab91f0a9SRafal Ozieblo 	/* tsu_timer_incr register must be written after
107ab91f0a9SRafal Ozieblo 	 * the tsu_timer_incr_sub_ns register and the write operation
108ab91f0a9SRafal Ozieblo 	 * will cause the value written to the tsu_timer_incr_sub_ns register
109ab91f0a9SRafal Ozieblo 	 * to take effect.
110ab91f0a9SRafal Ozieblo 	 */
111ab91f0a9SRafal Ozieblo 	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
1127ad342bcSHarini Katakam 	/* RegBit[15:0] = Subns[23:8]; RegBit[31:24] = Subns[7:0] */
1137ad342bcSHarini Katakam 	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCRL, incr_spec->sub_ns) |
1147ad342bcSHarini Katakam 		   GEM_BF(SUBNSINCRH, (incr_spec->sub_ns >>
1157ad342bcSHarini Katakam 			  GEM_SUBNSINCRL_SIZE)));
116ab91f0a9SRafal Ozieblo 	gem_writel(bp, TI, GEM_BF(NSINCR, incr_spec->ns));
117ab91f0a9SRafal Ozieblo 	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
118ab91f0a9SRafal Ozieblo 
119ab91f0a9SRafal Ozieblo 	return 0;
120ab91f0a9SRafal Ozieblo }
121ab91f0a9SRafal Ozieblo 
gem_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)122ab91f0a9SRafal Ozieblo static int gem_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
123ab91f0a9SRafal Ozieblo {
124ab91f0a9SRafal Ozieblo 	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
125ab91f0a9SRafal Ozieblo 	struct tsu_incr incr_spec;
126ab91f0a9SRafal Ozieblo 	bool neg_adj = false;
127ab91f0a9SRafal Ozieblo 	u32 word;
128ab91f0a9SRafal Ozieblo 	u64 adj;
129ab91f0a9SRafal Ozieblo 
130ab91f0a9SRafal Ozieblo 	if (scaled_ppm < 0) {
131ab91f0a9SRafal Ozieblo 		neg_adj = true;
132ab91f0a9SRafal Ozieblo 		scaled_ppm = -scaled_ppm;
133ab91f0a9SRafal Ozieblo 	}
134ab91f0a9SRafal Ozieblo 
135ab91f0a9SRafal Ozieblo 	/* Adjustment is relative to base frequency */
136ab91f0a9SRafal Ozieblo 	incr_spec.sub_ns = bp->tsu_incr.sub_ns;
137ab91f0a9SRafal Ozieblo 	incr_spec.ns = bp->tsu_incr.ns;
138ab91f0a9SRafal Ozieblo 
139ab91f0a9SRafal Ozieblo 	/* scaling: unused(8bit) | ns(8bit) | fractions(16bit) */
140ab91f0a9SRafal Ozieblo 	word = ((u64)incr_spec.ns << GEM_SUBNSINCR_SIZE) + incr_spec.sub_ns;
141ab91f0a9SRafal Ozieblo 	adj = (u64)scaled_ppm * word;
142ab91f0a9SRafal Ozieblo 	/* Divide with rounding, equivalent to floating dividing:
143ab91f0a9SRafal Ozieblo 	 * (temp / USEC_PER_SEC) + 0.5
144ab91f0a9SRafal Ozieblo 	 */
145ab91f0a9SRafal Ozieblo 	adj += (USEC_PER_SEC >> 1);
146a8ee4dc1SHarini Katakam 	adj >>= PPM_FRACTION; /* remove fractions */
147ab91f0a9SRafal Ozieblo 	adj = div_u64(adj, USEC_PER_SEC);
148ab91f0a9SRafal Ozieblo 	adj = neg_adj ? (word - adj) : (word + adj);
149ab91f0a9SRafal Ozieblo 
150ab91f0a9SRafal Ozieblo 	incr_spec.ns = (adj >> GEM_SUBNSINCR_SIZE)
151ab91f0a9SRafal Ozieblo 			& ((1 << GEM_NSINCR_SIZE) - 1);
152ab91f0a9SRafal Ozieblo 	incr_spec.sub_ns = adj & ((1 << GEM_SUBNSINCR_SIZE) - 1);
153ab91f0a9SRafal Ozieblo 	gem_tsu_incr_set(bp, &incr_spec);
154ab91f0a9SRafal Ozieblo 	return 0;
155ab91f0a9SRafal Ozieblo }
156ab91f0a9SRafal Ozieblo 
gem_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)157ab91f0a9SRafal Ozieblo static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
158ab91f0a9SRafal Ozieblo {
159ab91f0a9SRafal Ozieblo 	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
160ab91f0a9SRafal Ozieblo 	struct timespec64 now, then = ns_to_timespec64(delta);
161ab91f0a9SRafal Ozieblo 	u32 adj, sign = 0;
162ab91f0a9SRafal Ozieblo 
163ab91f0a9SRafal Ozieblo 	if (delta < 0) {
164ab91f0a9SRafal Ozieblo 		sign = 1;
165ab91f0a9SRafal Ozieblo 		delta = -delta;
166ab91f0a9SRafal Ozieblo 	}
167ab91f0a9SRafal Ozieblo 
168ab91f0a9SRafal Ozieblo 	if (delta > TSU_NSEC_MAX_VAL) {
169e51bb5c2SLars-Peter Clausen 		gem_tsu_get_time(&bp->ptp_clock_info, &now, NULL);
170ab91f0a9SRafal Ozieblo 		now = timespec64_add(now, then);
171ab91f0a9SRafal Ozieblo 
172ab91f0a9SRafal Ozieblo 		gem_tsu_set_time(&bp->ptp_clock_info,
173ab91f0a9SRafal Ozieblo 				 (const struct timespec64 *)&now);
174ab91f0a9SRafal Ozieblo 	} else {
175ab91f0a9SRafal Ozieblo 		adj = (sign << GEM_ADDSUB_OFFSET) | delta;
176ab91f0a9SRafal Ozieblo 
177ab91f0a9SRafal Ozieblo 		gem_writel(bp, TA, adj);
178ab91f0a9SRafal Ozieblo 	}
179ab91f0a9SRafal Ozieblo 
180ab91f0a9SRafal Ozieblo 	return 0;
181ab91f0a9SRafal Ozieblo }
182ab91f0a9SRafal Ozieblo 
gem_ptp_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)183ab91f0a9SRafal Ozieblo static int gem_ptp_enable(struct ptp_clock_info *ptp,
184ab91f0a9SRafal Ozieblo 			  struct ptp_clock_request *rq, int on)
185ab91f0a9SRafal Ozieblo {
186ab91f0a9SRafal Ozieblo 	return -EOPNOTSUPP;
187ab91f0a9SRafal Ozieblo }
188ab91f0a9SRafal Ozieblo 
189b6d08bd8SBhumika Goyal static const struct ptp_clock_info gem_ptp_caps_template = {
190ab91f0a9SRafal Ozieblo 	.owner		= THIS_MODULE,
191ab91f0a9SRafal Ozieblo 	.name		= GEM_PTP_TIMER_NAME,
192ab91f0a9SRafal Ozieblo 	.max_adj	= 0,
193ab91f0a9SRafal Ozieblo 	.n_alarm	= 0,
194ab91f0a9SRafal Ozieblo 	.n_ext_ts	= 0,
195ab91f0a9SRafal Ozieblo 	.n_per_out	= 0,
196ab91f0a9SRafal Ozieblo 	.n_pins		= 0,
197ab91f0a9SRafal Ozieblo 	.pps		= 1,
198ab91f0a9SRafal Ozieblo 	.adjfine	= gem_ptp_adjfine,
199ab91f0a9SRafal Ozieblo 	.adjtime	= gem_ptp_adjtime,
200e51bb5c2SLars-Peter Clausen 	.gettimex64	= gem_tsu_get_time,
201ab91f0a9SRafal Ozieblo 	.settime64	= gem_tsu_set_time,
202ab91f0a9SRafal Ozieblo 	.enable		= gem_ptp_enable,
203ab91f0a9SRafal Ozieblo };
204ab91f0a9SRafal Ozieblo 
gem_ptp_init_timer(struct macb * bp)205ab91f0a9SRafal Ozieblo static void gem_ptp_init_timer(struct macb *bp)
206ab91f0a9SRafal Ozieblo {
207ab91f0a9SRafal Ozieblo 	u32 rem = 0;
208ab91f0a9SRafal Ozieblo 	u64 adj;
209ab91f0a9SRafal Ozieblo 
210ab91f0a9SRafal Ozieblo 	bp->tsu_incr.ns = div_u64_rem(NSEC_PER_SEC, bp->tsu_rate, &rem);
211ab91f0a9SRafal Ozieblo 	if (rem) {
212ab91f0a9SRafal Ozieblo 		adj = rem;
213ab91f0a9SRafal Ozieblo 		adj <<= GEM_SUBNSINCR_SIZE;
214ab91f0a9SRafal Ozieblo 		bp->tsu_incr.sub_ns = div_u64(adj, bp->tsu_rate);
215ab91f0a9SRafal Ozieblo 	} else {
216ab91f0a9SRafal Ozieblo 		bp->tsu_incr.sub_ns = 0;
217ab91f0a9SRafal Ozieblo 	}
218ab91f0a9SRafal Ozieblo }
219ab91f0a9SRafal Ozieblo 
gem_ptp_init_tsu(struct macb * bp)220ab91f0a9SRafal Ozieblo static void gem_ptp_init_tsu(struct macb *bp)
221ab91f0a9SRafal Ozieblo {
222ab91f0a9SRafal Ozieblo 	struct timespec64 ts;
223ab91f0a9SRafal Ozieblo 
224ab91f0a9SRafal Ozieblo 	/* 1. get current system time */
225ab91f0a9SRafal Ozieblo 	ts = ns_to_timespec64(ktime_to_ns(ktime_get_real()));
226ab91f0a9SRafal Ozieblo 
227ab91f0a9SRafal Ozieblo 	/* 2. set ptp timer */
228ab91f0a9SRafal Ozieblo 	gem_tsu_set_time(&bp->ptp_clock_info, &ts);
229ab91f0a9SRafal Ozieblo 
230ab91f0a9SRafal Ozieblo 	/* 3. set PTP timer increment value to BASE_INCREMENT */
231ab91f0a9SRafal Ozieblo 	gem_tsu_incr_set(bp, &bp->tsu_incr);
232ab91f0a9SRafal Ozieblo 
233ab91f0a9SRafal Ozieblo 	gem_writel(bp, TA, 0);
234ab91f0a9SRafal Ozieblo }
235ab91f0a9SRafal Ozieblo 
gem_ptp_clear_timer(struct macb * bp)236ab91f0a9SRafal Ozieblo static void gem_ptp_clear_timer(struct macb *bp)
237ab91f0a9SRafal Ozieblo {
238ab91f0a9SRafal Ozieblo 	bp->tsu_incr.sub_ns = 0;
239ab91f0a9SRafal Ozieblo 	bp->tsu_incr.ns = 0;
240ab91f0a9SRafal Ozieblo 
241ab91f0a9SRafal Ozieblo 	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, 0));
242ab91f0a9SRafal Ozieblo 	gem_writel(bp, TI, GEM_BF(NSINCR, 0));
243ab91f0a9SRafal Ozieblo 	gem_writel(bp, TA, 0);
244ab91f0a9SRafal Ozieblo }
245ab91f0a9SRafal Ozieblo 
gem_hw_timestamp(struct macb * bp,u32 dma_desc_ts_1,u32 dma_desc_ts_2,struct timespec64 * ts)246ab91f0a9SRafal Ozieblo static int gem_hw_timestamp(struct macb *bp, u32 dma_desc_ts_1,
247ab91f0a9SRafal Ozieblo 			    u32 dma_desc_ts_2, struct timespec64 *ts)
248ab91f0a9SRafal Ozieblo {
249ab91f0a9SRafal Ozieblo 	struct timespec64 tsu;
250ab91f0a9SRafal Ozieblo 
251ab91f0a9SRafal Ozieblo 	ts->tv_sec = (GEM_BFEXT(DMA_SECH, dma_desc_ts_2) << GEM_DMA_SECL_SIZE) |
252ab91f0a9SRafal Ozieblo 			GEM_BFEXT(DMA_SECL, dma_desc_ts_1);
253ab91f0a9SRafal Ozieblo 	ts->tv_nsec = GEM_BFEXT(DMA_NSEC, dma_desc_ts_1);
254ab91f0a9SRafal Ozieblo 
255ab91f0a9SRafal Ozieblo 	/* TSU overlapping workaround
256ab91f0a9SRafal Ozieblo 	 * The timestamp only contains lower few bits of seconds,
257ab91f0a9SRafal Ozieblo 	 * so add value from 1588 timer
258ab91f0a9SRafal Ozieblo 	 */
259e51bb5c2SLars-Peter Clausen 	gem_tsu_get_time(&bp->ptp_clock_info, &tsu, NULL);
260ab91f0a9SRafal Ozieblo 
261*8c0d0fe0SHarini Katakam 	ts->tv_sec |= ((~GEM_DMA_SEC_MASK) & tsu.tv_sec);
262*8c0d0fe0SHarini Katakam 
263ab91f0a9SRafal Ozieblo 	/* If the top bit is set in the timestamp,
264ab91f0a9SRafal Ozieblo 	 * but not in 1588 timer, it has rolled over,
265ab91f0a9SRafal Ozieblo 	 * so subtract max size
266ab91f0a9SRafal Ozieblo 	 */
267ab91f0a9SRafal Ozieblo 	if ((ts->tv_sec & (GEM_DMA_SEC_TOP >> 1)) &&
268ab91f0a9SRafal Ozieblo 	    !(tsu.tv_sec & (GEM_DMA_SEC_TOP >> 1)))
269ab91f0a9SRafal Ozieblo 		ts->tv_sec -= GEM_DMA_SEC_TOP;
270ab91f0a9SRafal Ozieblo 
271ab91f0a9SRafal Ozieblo 	return 0;
272ab91f0a9SRafal Ozieblo }
273ab91f0a9SRafal Ozieblo 
gem_ptp_rxstamp(struct macb * bp,struct sk_buff * skb,struct macb_dma_desc * desc)274ab91f0a9SRafal Ozieblo void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb,
275ab91f0a9SRafal Ozieblo 		     struct macb_dma_desc *desc)
276ab91f0a9SRafal Ozieblo {
277ab91f0a9SRafal Ozieblo 	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
278ab91f0a9SRafal Ozieblo 	struct macb_dma_desc_ptp *desc_ptp;
279ab91f0a9SRafal Ozieblo 	struct timespec64 ts;
280ab91f0a9SRafal Ozieblo 
281ab91f0a9SRafal Ozieblo 	if (GEM_BFEXT(DMA_RXVALID, desc->addr)) {
282ab91f0a9SRafal Ozieblo 		desc_ptp = macb_ptp_desc(bp, desc);
28385520079SHarini Katakam 		/* Unlikely but check */
28485520079SHarini Katakam 		if (!desc_ptp) {
28585520079SHarini Katakam 			dev_warn_ratelimited(&bp->pdev->dev,
28685520079SHarini Katakam 					     "Timestamp not supported in BD\n");
28785520079SHarini Katakam 			return;
28885520079SHarini Katakam 		}
289ab91f0a9SRafal Ozieblo 		gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
290ab91f0a9SRafal Ozieblo 		memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
291ab91f0a9SRafal Ozieblo 		shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
292ab91f0a9SRafal Ozieblo 	}
293ab91f0a9SRafal Ozieblo }
294ab91f0a9SRafal Ozieblo 
gem_ptp_txstamp(struct macb * bp,struct sk_buff * skb,struct macb_dma_desc * desc)2958e7610e6SRobert Hancock void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb,
2968e7610e6SRobert Hancock 		     struct macb_dma_desc *desc)
297ab91f0a9SRafal Ozieblo {
298ab91f0a9SRafal Ozieblo 	struct skb_shared_hwtstamps shhwtstamps;
2998e7610e6SRobert Hancock 	struct macb_dma_desc_ptp *desc_ptp;
300ab91f0a9SRafal Ozieblo 	struct timespec64 ts;
301ab91f0a9SRafal Ozieblo 
3028e7610e6SRobert Hancock 	if (!GEM_BFEXT(DMA_TXVALID, desc->ctrl)) {
3038e7610e6SRobert Hancock 		dev_warn_ratelimited(&bp->pdev->dev,
3048e7610e6SRobert Hancock 				     "Timestamp not set in TX BD as expected\n");
3058e7610e6SRobert Hancock 		return;
3068e7610e6SRobert Hancock 	}
3078e7610e6SRobert Hancock 
3088e7610e6SRobert Hancock 	desc_ptp = macb_ptp_desc(bp, desc);
3098e7610e6SRobert Hancock 	/* Unlikely but check */
3108e7610e6SRobert Hancock 	if (!desc_ptp) {
3118e7610e6SRobert Hancock 		dev_warn_ratelimited(&bp->pdev->dev,
3128e7610e6SRobert Hancock 				     "Timestamp not supported in BD\n");
3138e7610e6SRobert Hancock 		return;
3148e7610e6SRobert Hancock 	}
3158e7610e6SRobert Hancock 
3168e7610e6SRobert Hancock 	/* ensure ts_1/ts_2 is loaded after ctrl (TX_USED check) */
3178e7610e6SRobert Hancock 	dma_rmb();
318ab91f0a9SRafal Ozieblo 	gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
3198e7610e6SRobert Hancock 
320ab91f0a9SRafal Ozieblo 	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
321ab91f0a9SRafal Ozieblo 	shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
322ab91f0a9SRafal Ozieblo 	skb_tstamp_tx(skb, &shhwtstamps);
323ab91f0a9SRafal Ozieblo }
324ab91f0a9SRafal Ozieblo 
gem_ptp_init(struct net_device * dev)325ab91f0a9SRafal Ozieblo void gem_ptp_init(struct net_device *dev)
326ab91f0a9SRafal Ozieblo {
327ab91f0a9SRafal Ozieblo 	struct macb *bp = netdev_priv(dev);
328ab91f0a9SRafal Ozieblo 
329ab91f0a9SRafal Ozieblo 	bp->ptp_clock_info = gem_ptp_caps_template;
330ab91f0a9SRafal Ozieblo 
331ab91f0a9SRafal Ozieblo 	/* nominal frequency and maximum adjustment in ppb */
332ab91f0a9SRafal Ozieblo 	bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
333ab91f0a9SRafal Ozieblo 	bp->ptp_clock_info.max_adj = bp->ptp_info->get_ptp_max_adj();
334ab91f0a9SRafal Ozieblo 	gem_ptp_init_timer(bp);
335ab91f0a9SRafal Ozieblo 	bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &dev->dev);
336ab91f0a9SRafal Ozieblo 	if (IS_ERR(bp->ptp_clock)) {
337ab91f0a9SRafal Ozieblo 		pr_err("ptp clock register failed: %ld\n",
338ab91f0a9SRafal Ozieblo 			PTR_ERR(bp->ptp_clock));
339ab91f0a9SRafal Ozieblo 		bp->ptp_clock = NULL;
340ab91f0a9SRafal Ozieblo 		return;
341ab91f0a9SRafal Ozieblo 	} else if (bp->ptp_clock == NULL) {
342ab91f0a9SRafal Ozieblo 		pr_err("ptp clock register failed\n");
343ab91f0a9SRafal Ozieblo 		return;
344ab91f0a9SRafal Ozieblo 	}
345ab91f0a9SRafal Ozieblo 
346ab91f0a9SRafal Ozieblo 	spin_lock_init(&bp->tsu_clk_lock);
347ab91f0a9SRafal Ozieblo 
348ab91f0a9SRafal Ozieblo 	gem_ptp_init_tsu(bp);
349ab91f0a9SRafal Ozieblo 
350ab91f0a9SRafal Ozieblo 	dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
351ab91f0a9SRafal Ozieblo 		 GEM_PTP_TIMER_NAME);
352ab91f0a9SRafal Ozieblo }
353ab91f0a9SRafal Ozieblo 
gem_ptp_remove(struct net_device * ndev)354ab91f0a9SRafal Ozieblo void gem_ptp_remove(struct net_device *ndev)
355ab91f0a9SRafal Ozieblo {
356ab91f0a9SRafal Ozieblo 	struct macb *bp = netdev_priv(ndev);
357ab91f0a9SRafal Ozieblo 
358ab91f0a9SRafal Ozieblo 	if (bp->ptp_clock)
359ab91f0a9SRafal Ozieblo 		ptp_clock_unregister(bp->ptp_clock);
360ab91f0a9SRafal Ozieblo 
361ab91f0a9SRafal Ozieblo 	gem_ptp_clear_timer(bp);
362ab91f0a9SRafal Ozieblo 
363ab91f0a9SRafal Ozieblo 	dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
364ab91f0a9SRafal Ozieblo 		 GEM_PTP_TIMER_NAME);
365ab91f0a9SRafal Ozieblo }
366ab91f0a9SRafal Ozieblo 
gem_ptp_set_ts_mode(struct macb * bp,enum macb_bd_control tx_bd_control,enum macb_bd_control rx_bd_control)367ab91f0a9SRafal Ozieblo static int gem_ptp_set_ts_mode(struct macb *bp,
368ab91f0a9SRafal Ozieblo 			       enum macb_bd_control tx_bd_control,
369ab91f0a9SRafal Ozieblo 			       enum macb_bd_control rx_bd_control)
370ab91f0a9SRafal Ozieblo {
371ab91f0a9SRafal Ozieblo 	gem_writel(bp, TXBDCTRL, GEM_BF(TXTSMODE, tx_bd_control));
372ab91f0a9SRafal Ozieblo 	gem_writel(bp, RXBDCTRL, GEM_BF(RXTSMODE, rx_bd_control));
373ab91f0a9SRafal Ozieblo 
374ab91f0a9SRafal Ozieblo 	return 0;
375ab91f0a9SRafal Ozieblo }
376ab91f0a9SRafal Ozieblo 
gem_get_hwtst(struct net_device * dev,struct ifreq * rq)377ab91f0a9SRafal Ozieblo int gem_get_hwtst(struct net_device *dev, struct ifreq *rq)
378ab91f0a9SRafal Ozieblo {
379ab91f0a9SRafal Ozieblo 	struct hwtstamp_config *tstamp_config;
380ab91f0a9SRafal Ozieblo 	struct macb *bp = netdev_priv(dev);
381ab91f0a9SRafal Ozieblo 
382ab91f0a9SRafal Ozieblo 	tstamp_config = &bp->tstamp_config;
383ab91f0a9SRafal Ozieblo 	if ((bp->hw_dma_cap & HW_DMA_CAP_PTP) == 0)
384ab91f0a9SRafal Ozieblo 		return -EOPNOTSUPP;
385ab91f0a9SRafal Ozieblo 
386ab91f0a9SRafal Ozieblo 	if (copy_to_user(rq->ifr_data, tstamp_config, sizeof(*tstamp_config)))
387ab91f0a9SRafal Ozieblo 		return -EFAULT;
388ab91f0a9SRafal Ozieblo 	else
389ab91f0a9SRafal Ozieblo 		return 0;
390ab91f0a9SRafal Ozieblo }
391ab91f0a9SRafal Ozieblo 
gem_ptp_set_one_step_sync(struct macb * bp,u8 enable)392263efe85SClaudiu Beznea static void gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)
393ab91f0a9SRafal Ozieblo {
394ab91f0a9SRafal Ozieblo 	u32 reg_val;
395ab91f0a9SRafal Ozieblo 
396ab91f0a9SRafal Ozieblo 	reg_val = macb_readl(bp, NCR);
397ab91f0a9SRafal Ozieblo 
398ab91f0a9SRafal Ozieblo 	if (enable)
399ab91f0a9SRafal Ozieblo 		macb_writel(bp, NCR, reg_val | MACB_BIT(OSSMODE));
400ab91f0a9SRafal Ozieblo 	else
401ab91f0a9SRafal Ozieblo 		macb_writel(bp, NCR, reg_val & ~MACB_BIT(OSSMODE));
402ab91f0a9SRafal Ozieblo }
403ab91f0a9SRafal Ozieblo 
gem_set_hwtst(struct net_device * dev,struct ifreq * ifr,int cmd)404ab91f0a9SRafal Ozieblo int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd)
405ab91f0a9SRafal Ozieblo {
406ab91f0a9SRafal Ozieblo 	enum macb_bd_control tx_bd_control = TSTAMP_DISABLED;
407ab91f0a9SRafal Ozieblo 	enum macb_bd_control rx_bd_control = TSTAMP_DISABLED;
408ab91f0a9SRafal Ozieblo 	struct hwtstamp_config *tstamp_config;
409ab91f0a9SRafal Ozieblo 	struct macb *bp = netdev_priv(dev);
410ab91f0a9SRafal Ozieblo 	u32 regval;
411ab91f0a9SRafal Ozieblo 
412ab91f0a9SRafal Ozieblo 	tstamp_config = &bp->tstamp_config;
413ab91f0a9SRafal Ozieblo 	if ((bp->hw_dma_cap & HW_DMA_CAP_PTP) == 0)
414ab91f0a9SRafal Ozieblo 		return -EOPNOTSUPP;
415ab91f0a9SRafal Ozieblo 
416ab91f0a9SRafal Ozieblo 	if (copy_from_user(tstamp_config, ifr->ifr_data,
417ab91f0a9SRafal Ozieblo 			   sizeof(*tstamp_config)))
418ab91f0a9SRafal Ozieblo 		return -EFAULT;
419ab91f0a9SRafal Ozieblo 
420ab91f0a9SRafal Ozieblo 	switch (tstamp_config->tx_type) {
421ab91f0a9SRafal Ozieblo 	case HWTSTAMP_TX_OFF:
422ab91f0a9SRafal Ozieblo 		break;
423ab91f0a9SRafal Ozieblo 	case HWTSTAMP_TX_ONESTEP_SYNC:
424263efe85SClaudiu Beznea 		gem_ptp_set_one_step_sync(bp, 1);
4255cebb40bSHarini Katakam 		tx_bd_control = TSTAMP_ALL_FRAMES;
4265cebb40bSHarini Katakam 		break;
427ab91f0a9SRafal Ozieblo 	case HWTSTAMP_TX_ON:
4285cebb40bSHarini Katakam 		gem_ptp_set_one_step_sync(bp, 0);
429ab91f0a9SRafal Ozieblo 		tx_bd_control = TSTAMP_ALL_FRAMES;
430ab91f0a9SRafal Ozieblo 		break;
431ab91f0a9SRafal Ozieblo 	default:
432ab91f0a9SRafal Ozieblo 		return -ERANGE;
433ab91f0a9SRafal Ozieblo 	}
434ab91f0a9SRafal Ozieblo 
435ab91f0a9SRafal Ozieblo 	switch (tstamp_config->rx_filter) {
436ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_NONE:
437ab91f0a9SRafal Ozieblo 		break;
438ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
439ab91f0a9SRafal Ozieblo 		break;
440ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
441ab91f0a9SRafal Ozieblo 		break;
442ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
443ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
444ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
445ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
446ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
447ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
448ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
449ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
450ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
451ab91f0a9SRafal Ozieblo 		rx_bd_control =  TSTAMP_ALL_PTP_FRAMES;
452ab91f0a9SRafal Ozieblo 		tstamp_config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
453ab91f0a9SRafal Ozieblo 		regval = macb_readl(bp, NCR);
454ab91f0a9SRafal Ozieblo 		macb_writel(bp, NCR, (regval | MACB_BIT(SRTSM)));
455ab91f0a9SRafal Ozieblo 		break;
456ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
457ab91f0a9SRafal Ozieblo 	case HWTSTAMP_FILTER_ALL:
458ab91f0a9SRafal Ozieblo 		rx_bd_control = TSTAMP_ALL_FRAMES;
459ab91f0a9SRafal Ozieblo 		tstamp_config->rx_filter = HWTSTAMP_FILTER_ALL;
460ab91f0a9SRafal Ozieblo 		break;
461ab91f0a9SRafal Ozieblo 	default:
462ab91f0a9SRafal Ozieblo 		tstamp_config->rx_filter = HWTSTAMP_FILTER_NONE;
463ab91f0a9SRafal Ozieblo 		return -ERANGE;
464ab91f0a9SRafal Ozieblo 	}
465ab91f0a9SRafal Ozieblo 
466ab91f0a9SRafal Ozieblo 	if (gem_ptp_set_ts_mode(bp, tx_bd_control, rx_bd_control) != 0)
467ab91f0a9SRafal Ozieblo 		return -ERANGE;
468ab91f0a9SRafal Ozieblo 
469ab91f0a9SRafal Ozieblo 	if (copy_to_user(ifr->ifr_data, tstamp_config, sizeof(*tstamp_config)))
470ab91f0a9SRafal Ozieblo 		return -EFAULT;
471ab91f0a9SRafal Ozieblo 	else
472ab91f0a9SRafal Ozieblo 		return 0;
473ab91f0a9SRafal Ozieblo }
474ab91f0a9SRafal Ozieblo 
475