xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* Atlantic Network Driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2014-2019 aQuantia Corporation
5*4882a593Smuzhiyun  * Copyright (C) 2019-2020 Marvell International Ltd.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /* File aq_ptp.c:
9*4882a593Smuzhiyun  * Definition of functions for Linux PTP support.
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/ptp_clock_kernel.h>
13*4882a593Smuzhiyun #include <linux/ptp_classify.h>
14*4882a593Smuzhiyun #include <linux/interrupt.h>
15*4882a593Smuzhiyun #include <linux/clocksource.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "aq_nic.h"
18*4882a593Smuzhiyun #include "aq_ptp.h"
19*4882a593Smuzhiyun #include "aq_ring.h"
20*4882a593Smuzhiyun #include "aq_phy.h"
21*4882a593Smuzhiyun #include "aq_filters.h"
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define AQ_PTP_TX_TIMEOUT        (HZ *  10)
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define POLL_SYNC_TIMER_MS 15
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun enum ptp_speed_offsets {
30*4882a593Smuzhiyun 	ptp_offset_idx_10 = 0,
31*4882a593Smuzhiyun 	ptp_offset_idx_100,
32*4882a593Smuzhiyun 	ptp_offset_idx_1000,
33*4882a593Smuzhiyun 	ptp_offset_idx_2500,
34*4882a593Smuzhiyun 	ptp_offset_idx_5000,
35*4882a593Smuzhiyun 	ptp_offset_idx_10000,
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun struct ptp_skb_ring {
39*4882a593Smuzhiyun 	struct sk_buff **buff;
40*4882a593Smuzhiyun 	spinlock_t lock;
41*4882a593Smuzhiyun 	unsigned int size;
42*4882a593Smuzhiyun 	unsigned int head;
43*4882a593Smuzhiyun 	unsigned int tail;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun struct ptp_tx_timeout {
47*4882a593Smuzhiyun 	spinlock_t lock;
48*4882a593Smuzhiyun 	bool active;
49*4882a593Smuzhiyun 	unsigned long tx_start;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun struct aq_ptp_s {
53*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic;
54*4882a593Smuzhiyun 	struct hwtstamp_config hwtstamp_config;
55*4882a593Smuzhiyun 	spinlock_t ptp_lock;
56*4882a593Smuzhiyun 	spinlock_t ptp_ring_lock;
57*4882a593Smuzhiyun 	struct ptp_clock *ptp_clock;
58*4882a593Smuzhiyun 	struct ptp_clock_info ptp_info;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	atomic_t offset_egress;
61*4882a593Smuzhiyun 	atomic_t offset_ingress;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	struct aq_ring_param_s ptp_ring_param;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	struct ptp_tx_timeout ptp_tx_timeout;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	unsigned int idx_vector;
68*4882a593Smuzhiyun 	struct napi_struct napi;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	struct aq_ring_s ptp_tx;
71*4882a593Smuzhiyun 	struct aq_ring_s ptp_rx;
72*4882a593Smuzhiyun 	struct aq_ring_s hwts_rx;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	struct ptp_skb_ring skb_ring;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	struct aq_rx_filter_l3l4 udp_filter;
77*4882a593Smuzhiyun 	struct aq_rx_filter_l2 eth_type_filter;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	struct delayed_work poll_sync;
80*4882a593Smuzhiyun 	u32 poll_timeout_ms;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	bool extts_pin_enabled;
83*4882a593Smuzhiyun 	u64 last_sync1588_ts;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	bool a1_ptp;
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun struct ptp_tm_offset {
89*4882a593Smuzhiyun 	unsigned int mbps;
90*4882a593Smuzhiyun 	int egress;
91*4882a593Smuzhiyun 	int ingress;
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static struct ptp_tm_offset ptp_offset[6];
95*4882a593Smuzhiyun 
aq_ptp_tm_offset_set(struct aq_nic_s * aq_nic,unsigned int mbps)96*4882a593Smuzhiyun void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
99*4882a593Smuzhiyun 	int i, egress, ingress;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	if (!aq_ptp)
102*4882a593Smuzhiyun 		return;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	egress = 0;
105*4882a593Smuzhiyun 	ingress = 0;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ptp_offset); i++) {
108*4882a593Smuzhiyun 		if (mbps == ptp_offset[i].mbps) {
109*4882a593Smuzhiyun 			egress = ptp_offset[i].egress;
110*4882a593Smuzhiyun 			ingress = ptp_offset[i].ingress;
111*4882a593Smuzhiyun 			break;
112*4882a593Smuzhiyun 		}
113*4882a593Smuzhiyun 	}
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	atomic_set(&aq_ptp->offset_egress, egress);
116*4882a593Smuzhiyun 	atomic_set(&aq_ptp->offset_ingress, ingress);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
__aq_ptp_skb_put(struct ptp_skb_ring * ring,struct sk_buff * skb)119*4882a593Smuzhiyun static int __aq_ptp_skb_put(struct ptp_skb_ring *ring, struct sk_buff *skb)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	unsigned int next_head = (ring->head + 1) % ring->size;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	if (next_head == ring->tail)
124*4882a593Smuzhiyun 		return -ENOMEM;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	ring->buff[ring->head] = skb_get(skb);
127*4882a593Smuzhiyun 	ring->head = next_head;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
aq_ptp_skb_put(struct ptp_skb_ring * ring,struct sk_buff * skb)132*4882a593Smuzhiyun static int aq_ptp_skb_put(struct ptp_skb_ring *ring, struct sk_buff *skb)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	unsigned long flags;
135*4882a593Smuzhiyun 	int ret;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	spin_lock_irqsave(&ring->lock, flags);
138*4882a593Smuzhiyun 	ret = __aq_ptp_skb_put(ring, skb);
139*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ring->lock, flags);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	return ret;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
__aq_ptp_skb_get(struct ptp_skb_ring * ring)144*4882a593Smuzhiyun static struct sk_buff *__aq_ptp_skb_get(struct ptp_skb_ring *ring)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct sk_buff *skb;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	if (ring->tail == ring->head)
149*4882a593Smuzhiyun 		return NULL;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	skb = ring->buff[ring->tail];
152*4882a593Smuzhiyun 	ring->tail = (ring->tail + 1) % ring->size;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	return skb;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
aq_ptp_skb_get(struct ptp_skb_ring * ring)157*4882a593Smuzhiyun static struct sk_buff *aq_ptp_skb_get(struct ptp_skb_ring *ring)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun 	unsigned long flags;
160*4882a593Smuzhiyun 	struct sk_buff *skb;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	spin_lock_irqsave(&ring->lock, flags);
163*4882a593Smuzhiyun 	skb = __aq_ptp_skb_get(ring);
164*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ring->lock, flags);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return skb;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
aq_ptp_skb_buf_len(struct ptp_skb_ring * ring)169*4882a593Smuzhiyun static unsigned int aq_ptp_skb_buf_len(struct ptp_skb_ring *ring)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	unsigned long flags;
172*4882a593Smuzhiyun 	unsigned int len;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	spin_lock_irqsave(&ring->lock, flags);
175*4882a593Smuzhiyun 	len = (ring->head >= ring->tail) ?
176*4882a593Smuzhiyun 	ring->head - ring->tail :
177*4882a593Smuzhiyun 	ring->size - ring->tail + ring->head;
178*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ring->lock, flags);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	return len;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
aq_ptp_skb_ring_init(struct ptp_skb_ring * ring,unsigned int size)183*4882a593Smuzhiyun static int aq_ptp_skb_ring_init(struct ptp_skb_ring *ring, unsigned int size)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	struct sk_buff **buff = kmalloc(sizeof(*buff) * size, GFP_KERNEL);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	if (!buff)
188*4882a593Smuzhiyun 		return -ENOMEM;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	spin_lock_init(&ring->lock);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	ring->buff = buff;
193*4882a593Smuzhiyun 	ring->size = size;
194*4882a593Smuzhiyun 	ring->head = 0;
195*4882a593Smuzhiyun 	ring->tail = 0;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return 0;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
aq_ptp_skb_ring_clean(struct ptp_skb_ring * ring)200*4882a593Smuzhiyun static void aq_ptp_skb_ring_clean(struct ptp_skb_ring *ring)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	struct sk_buff *skb;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	while ((skb = aq_ptp_skb_get(ring)) != NULL)
205*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
aq_ptp_skb_ring_release(struct ptp_skb_ring * ring)208*4882a593Smuzhiyun static void aq_ptp_skb_ring_release(struct ptp_skb_ring *ring)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	if (ring->buff) {
211*4882a593Smuzhiyun 		aq_ptp_skb_ring_clean(ring);
212*4882a593Smuzhiyun 		kfree(ring->buff);
213*4882a593Smuzhiyun 		ring->buff = NULL;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun 
aq_ptp_tx_timeout_init(struct ptp_tx_timeout * timeout)217*4882a593Smuzhiyun static void aq_ptp_tx_timeout_init(struct ptp_tx_timeout *timeout)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	spin_lock_init(&timeout->lock);
220*4882a593Smuzhiyun 	timeout->active = false;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
aq_ptp_tx_timeout_start(struct aq_ptp_s * aq_ptp)223*4882a593Smuzhiyun static void aq_ptp_tx_timeout_start(struct aq_ptp_s *aq_ptp)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun 	struct ptp_tx_timeout *timeout = &aq_ptp->ptp_tx_timeout;
226*4882a593Smuzhiyun 	unsigned long flags;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	spin_lock_irqsave(&timeout->lock, flags);
229*4882a593Smuzhiyun 	timeout->active = true;
230*4882a593Smuzhiyun 	timeout->tx_start = jiffies;
231*4882a593Smuzhiyun 	spin_unlock_irqrestore(&timeout->lock, flags);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
aq_ptp_tx_timeout_update(struct aq_ptp_s * aq_ptp)234*4882a593Smuzhiyun static void aq_ptp_tx_timeout_update(struct aq_ptp_s *aq_ptp)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	if (!aq_ptp_skb_buf_len(&aq_ptp->skb_ring)) {
237*4882a593Smuzhiyun 		struct ptp_tx_timeout *timeout = &aq_ptp->ptp_tx_timeout;
238*4882a593Smuzhiyun 		unsigned long flags;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		spin_lock_irqsave(&timeout->lock, flags);
241*4882a593Smuzhiyun 		timeout->active = false;
242*4882a593Smuzhiyun 		spin_unlock_irqrestore(&timeout->lock, flags);
243*4882a593Smuzhiyun 	}
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
aq_ptp_tx_timeout_check(struct aq_ptp_s * aq_ptp)246*4882a593Smuzhiyun static void aq_ptp_tx_timeout_check(struct aq_ptp_s *aq_ptp)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun 	struct ptp_tx_timeout *timeout = &aq_ptp->ptp_tx_timeout;
249*4882a593Smuzhiyun 	unsigned long flags;
250*4882a593Smuzhiyun 	bool timeout_flag;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	timeout_flag = false;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	spin_lock_irqsave(&timeout->lock, flags);
255*4882a593Smuzhiyun 	if (timeout->active) {
256*4882a593Smuzhiyun 		timeout_flag = time_is_before_jiffies(timeout->tx_start +
257*4882a593Smuzhiyun 						      AQ_PTP_TX_TIMEOUT);
258*4882a593Smuzhiyun 		/* reset active flag if timeout detected */
259*4882a593Smuzhiyun 		if (timeout_flag)
260*4882a593Smuzhiyun 			timeout->active = false;
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 	spin_unlock_irqrestore(&timeout->lock, flags);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	if (timeout_flag) {
265*4882a593Smuzhiyun 		aq_ptp_skb_ring_clean(&aq_ptp->skb_ring);
266*4882a593Smuzhiyun 		netdev_err(aq_ptp->aq_nic->ndev,
267*4882a593Smuzhiyun 			   "PTP Timeout. Clearing Tx Timestamp SKBs\n");
268*4882a593Smuzhiyun 	}
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun /* aq_ptp_adjfine
272*4882a593Smuzhiyun  * @ptp: the ptp clock structure
273*4882a593Smuzhiyun  * @ppb: parts per billion adjustment from base
274*4882a593Smuzhiyun  *
275*4882a593Smuzhiyun  * adjust the frequency of the ptp cycle counter by the
276*4882a593Smuzhiyun  * indicated ppb from the base frequency.
277*4882a593Smuzhiyun  */
aq_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)278*4882a593Smuzhiyun static int aq_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
281*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	mutex_lock(&aq_nic->fwreq_mutex);
284*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_adj_clock_freq(aq_nic->aq_hw,
285*4882a593Smuzhiyun 					     scaled_ppm_to_ppb(scaled_ppm));
286*4882a593Smuzhiyun 	mutex_unlock(&aq_nic->fwreq_mutex);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	return 0;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun /* aq_ptp_adjtime
292*4882a593Smuzhiyun  * @ptp: the ptp clock structure
293*4882a593Smuzhiyun  * @delta: offset to adjust the cycle counter by
294*4882a593Smuzhiyun  *
295*4882a593Smuzhiyun  * adjust the timer by resetting the timecounter structure.
296*4882a593Smuzhiyun  */
aq_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)297*4882a593Smuzhiyun static int aq_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
300*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
301*4882a593Smuzhiyun 	unsigned long flags;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	spin_lock_irqsave(&aq_ptp->ptp_lock, flags);
304*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_adj_sys_clock(aq_nic->aq_hw, delta);
305*4882a593Smuzhiyun 	spin_unlock_irqrestore(&aq_ptp->ptp_lock, flags);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	return 0;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun /* aq_ptp_gettime
311*4882a593Smuzhiyun  * @ptp: the ptp clock structure
312*4882a593Smuzhiyun  * @ts: timespec structure to hold the current time value
313*4882a593Smuzhiyun  *
314*4882a593Smuzhiyun  * read the timecounter and return the correct value on ns,
315*4882a593Smuzhiyun  * after converting it into a struct timespec.
316*4882a593Smuzhiyun  */
aq_ptp_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)317*4882a593Smuzhiyun static int aq_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
320*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
321*4882a593Smuzhiyun 	unsigned long flags;
322*4882a593Smuzhiyun 	u64 ns;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	spin_lock_irqsave(&aq_ptp->ptp_lock, flags);
325*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_get_ptp_ts(aq_nic->aq_hw, &ns);
326*4882a593Smuzhiyun 	spin_unlock_irqrestore(&aq_ptp->ptp_lock, flags);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	*ts = ns_to_timespec64(ns);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	return 0;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun /* aq_ptp_settime
334*4882a593Smuzhiyun  * @ptp: the ptp clock structure
335*4882a593Smuzhiyun  * @ts: the timespec containing the new time for the cycle counter
336*4882a593Smuzhiyun  *
337*4882a593Smuzhiyun  * reset the timecounter to use a new base value instead of the kernel
338*4882a593Smuzhiyun  * wall timer value.
339*4882a593Smuzhiyun  */
aq_ptp_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)340*4882a593Smuzhiyun static int aq_ptp_settime(struct ptp_clock_info *ptp,
341*4882a593Smuzhiyun 			  const struct timespec64 *ts)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
344*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
345*4882a593Smuzhiyun 	unsigned long flags;
346*4882a593Smuzhiyun 	u64 ns = timespec64_to_ns(ts);
347*4882a593Smuzhiyun 	u64 now;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	spin_lock_irqsave(&aq_ptp->ptp_lock, flags);
350*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_get_ptp_ts(aq_nic->aq_hw, &now);
351*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_adj_sys_clock(aq_nic->aq_hw, (s64)ns - (s64)now);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	spin_unlock_irqrestore(&aq_ptp->ptp_lock, flags);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	return 0;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
aq_ptp_convert_to_hwtstamp(struct aq_ptp_s * aq_ptp,struct skb_shared_hwtstamps * hwtstamp,u64 timestamp)358*4882a593Smuzhiyun static void aq_ptp_convert_to_hwtstamp(struct aq_ptp_s *aq_ptp,
359*4882a593Smuzhiyun 				       struct skb_shared_hwtstamps *hwtstamp,
360*4882a593Smuzhiyun 				       u64 timestamp)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	memset(hwtstamp, 0, sizeof(*hwtstamp));
363*4882a593Smuzhiyun 	hwtstamp->hwtstamp = ns_to_ktime(timestamp);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
aq_ptp_hw_pin_conf(struct aq_nic_s * aq_nic,u32 pin_index,u64 start,u64 period)366*4882a593Smuzhiyun static int aq_ptp_hw_pin_conf(struct aq_nic_s *aq_nic, u32 pin_index, u64 start,
367*4882a593Smuzhiyun 			      u64 period)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	if (period)
370*4882a593Smuzhiyun 		netdev_dbg(aq_nic->ndev,
371*4882a593Smuzhiyun 			   "Enable GPIO %d pulsing, start time %llu, period %u\n",
372*4882a593Smuzhiyun 			   pin_index, start, (u32)period);
373*4882a593Smuzhiyun 	else
374*4882a593Smuzhiyun 		netdev_dbg(aq_nic->ndev,
375*4882a593Smuzhiyun 			   "Disable GPIO %d pulsing, start time %llu, period %u\n",
376*4882a593Smuzhiyun 			   pin_index, start, (u32)period);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	/* Notify hardware of request to being sending pulses.
379*4882a593Smuzhiyun 	 * If period is ZERO then pulsen is disabled.
380*4882a593Smuzhiyun 	 */
381*4882a593Smuzhiyun 	mutex_lock(&aq_nic->fwreq_mutex);
382*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_gpio_pulse(aq_nic->aq_hw, pin_index,
383*4882a593Smuzhiyun 					 start, (u32)period);
384*4882a593Smuzhiyun 	mutex_unlock(&aq_nic->fwreq_mutex);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	return 0;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun 
aq_ptp_perout_pin_configure(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)389*4882a593Smuzhiyun static int aq_ptp_perout_pin_configure(struct ptp_clock_info *ptp,
390*4882a593Smuzhiyun 				       struct ptp_clock_request *rq, int on)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
393*4882a593Smuzhiyun 	struct ptp_clock_time *t = &rq->perout.period;
394*4882a593Smuzhiyun 	struct ptp_clock_time *s = &rq->perout.start;
395*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
396*4882a593Smuzhiyun 	u64 start, period;
397*4882a593Smuzhiyun 	u32 pin_index = rq->perout.index;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	/* verify the request channel is there */
400*4882a593Smuzhiyun 	if (pin_index >= ptp->n_per_out)
401*4882a593Smuzhiyun 		return -EINVAL;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	/* we cannot support periods greater
404*4882a593Smuzhiyun 	 * than 4 seconds due to reg limit
405*4882a593Smuzhiyun 	 */
406*4882a593Smuzhiyun 	if (t->sec > 4 || t->sec < 0)
407*4882a593Smuzhiyun 		return -ERANGE;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	/* convert to unsigned 64b ns,
410*4882a593Smuzhiyun 	 * verify we can put it in a 32b register
411*4882a593Smuzhiyun 	 */
412*4882a593Smuzhiyun 	period = on ? t->sec * NSEC_PER_SEC + t->nsec : 0;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	/* verify the value is in range supported by hardware */
415*4882a593Smuzhiyun 	if (period > U32_MAX)
416*4882a593Smuzhiyun 		return -ERANGE;
417*4882a593Smuzhiyun 	/* convert to unsigned 64b ns */
418*4882a593Smuzhiyun 	/* TODO convert to AQ time */
419*4882a593Smuzhiyun 	start = on ? s->sec * NSEC_PER_SEC + s->nsec : 0;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	aq_ptp_hw_pin_conf(aq_nic, pin_index, start, period);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return 0;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
aq_ptp_pps_pin_configure(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)426*4882a593Smuzhiyun static int aq_ptp_pps_pin_configure(struct ptp_clock_info *ptp,
427*4882a593Smuzhiyun 				    struct ptp_clock_request *rq, int on)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
430*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
431*4882a593Smuzhiyun 	u64 start, period;
432*4882a593Smuzhiyun 	u32 pin_index = 0;
433*4882a593Smuzhiyun 	u32 rest = 0;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	/* verify the request channel is there */
436*4882a593Smuzhiyun 	if (pin_index >= ptp->n_per_out)
437*4882a593Smuzhiyun 		return -EINVAL;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_get_ptp_ts(aq_nic->aq_hw, &start);
440*4882a593Smuzhiyun 	div_u64_rem(start, NSEC_PER_SEC, &rest);
441*4882a593Smuzhiyun 	period = on ? NSEC_PER_SEC : 0; /* PPS - pulse per second */
442*4882a593Smuzhiyun 	start = on ? start - rest + NSEC_PER_SEC *
443*4882a593Smuzhiyun 		(rest > 990000000LL ? 2 : 1) : 0;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	aq_ptp_hw_pin_conf(aq_nic, pin_index, start, period);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	return 0;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
aq_ptp_extts_pin_ctrl(struct aq_ptp_s * aq_ptp)450*4882a593Smuzhiyun static void aq_ptp_extts_pin_ctrl(struct aq_ptp_s *aq_ptp)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
453*4882a593Smuzhiyun 	u32 enable = aq_ptp->extts_pin_enabled;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	if (aq_nic->aq_hw_ops->hw_extts_gpio_enable)
456*4882a593Smuzhiyun 		aq_nic->aq_hw_ops->hw_extts_gpio_enable(aq_nic->aq_hw, 0,
457*4882a593Smuzhiyun 							enable);
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun 
aq_ptp_extts_pin_configure(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)460*4882a593Smuzhiyun static int aq_ptp_extts_pin_configure(struct ptp_clock_info *ptp,
461*4882a593Smuzhiyun 				      struct ptp_clock_request *rq, int on)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	u32 pin_index = rq->extts.index;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	if (pin_index >= ptp->n_ext_ts)
468*4882a593Smuzhiyun 		return -EINVAL;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	aq_ptp->extts_pin_enabled = !!on;
471*4882a593Smuzhiyun 	if (on) {
472*4882a593Smuzhiyun 		aq_ptp->poll_timeout_ms = POLL_SYNC_TIMER_MS;
473*4882a593Smuzhiyun 		cancel_delayed_work_sync(&aq_ptp->poll_sync);
474*4882a593Smuzhiyun 		schedule_delayed_work(&aq_ptp->poll_sync,
475*4882a593Smuzhiyun 				      msecs_to_jiffies(aq_ptp->poll_timeout_ms));
476*4882a593Smuzhiyun 	}
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	aq_ptp_extts_pin_ctrl(aq_ptp);
479*4882a593Smuzhiyun 	return 0;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun /* aq_ptp_gpio_feature_enable
483*4882a593Smuzhiyun  * @ptp: the ptp clock structure
484*4882a593Smuzhiyun  * @rq: the requested feature to change
485*4882a593Smuzhiyun  * @on: whether to enable or disable the feature
486*4882a593Smuzhiyun  */
aq_ptp_gpio_feature_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)487*4882a593Smuzhiyun static int aq_ptp_gpio_feature_enable(struct ptp_clock_info *ptp,
488*4882a593Smuzhiyun 				      struct ptp_clock_request *rq, int on)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun 	switch (rq->type) {
491*4882a593Smuzhiyun 	case PTP_CLK_REQ_EXTTS:
492*4882a593Smuzhiyun 		return aq_ptp_extts_pin_configure(ptp, rq, on);
493*4882a593Smuzhiyun 	case PTP_CLK_REQ_PEROUT:
494*4882a593Smuzhiyun 		return aq_ptp_perout_pin_configure(ptp, rq, on);
495*4882a593Smuzhiyun 	case PTP_CLK_REQ_PPS:
496*4882a593Smuzhiyun 		return aq_ptp_pps_pin_configure(ptp, rq, on);
497*4882a593Smuzhiyun 	default:
498*4882a593Smuzhiyun 		return -EOPNOTSUPP;
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	return 0;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun /* aq_ptp_verify
505*4882a593Smuzhiyun  * @ptp: the ptp clock structure
506*4882a593Smuzhiyun  * @pin: index of the pin in question
507*4882a593Smuzhiyun  * @func: the desired function to use
508*4882a593Smuzhiyun  * @chan: the function channel index to use
509*4882a593Smuzhiyun  */
aq_ptp_verify(struct ptp_clock_info * ptp,unsigned int pin,enum ptp_pin_function func,unsigned int chan)510*4882a593Smuzhiyun static int aq_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
511*4882a593Smuzhiyun 			 enum ptp_pin_function func, unsigned int chan)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	/* verify the requested pin is there */
514*4882a593Smuzhiyun 	if (!ptp->pin_config || pin >= ptp->n_pins)
515*4882a593Smuzhiyun 		return -EINVAL;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	/* enforce locked channels, no changing them */
518*4882a593Smuzhiyun 	if (chan != ptp->pin_config[pin].chan)
519*4882a593Smuzhiyun 		return -EINVAL;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	/* we want to keep the functions locked as well */
522*4882a593Smuzhiyun 	if (func != ptp->pin_config[pin].func)
523*4882a593Smuzhiyun 		return -EINVAL;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun /* aq_ptp_tx_hwtstamp - utility function which checks for TX time stamp
529*4882a593Smuzhiyun  * @adapter: the private adapter struct
530*4882a593Smuzhiyun  *
531*4882a593Smuzhiyun  * if the timestamp is valid, we convert it into the timecounter ns
532*4882a593Smuzhiyun  * value, then store that result into the hwtstamps structure which
533*4882a593Smuzhiyun  * is passed up the network stack
534*4882a593Smuzhiyun  */
aq_ptp_tx_hwtstamp(struct aq_nic_s * aq_nic,u64 timestamp)535*4882a593Smuzhiyun void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
538*4882a593Smuzhiyun 	struct sk_buff *skb = aq_ptp_skb_get(&aq_ptp->skb_ring);
539*4882a593Smuzhiyun 	struct skb_shared_hwtstamps hwtstamp;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	if (!skb) {
542*4882a593Smuzhiyun 		netdev_err(aq_nic->ndev, "have timestamp but tx_queues empty\n");
543*4882a593Smuzhiyun 		return;
544*4882a593Smuzhiyun 	}
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	timestamp += atomic_read(&aq_ptp->offset_egress);
547*4882a593Smuzhiyun 	aq_ptp_convert_to_hwtstamp(aq_ptp, &hwtstamp, timestamp);
548*4882a593Smuzhiyun 	skb_tstamp_tx(skb, &hwtstamp);
549*4882a593Smuzhiyun 	dev_kfree_skb_any(skb);
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	aq_ptp_tx_timeout_update(aq_ptp);
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun /* aq_ptp_rx_hwtstamp - utility function which checks for RX time stamp
555*4882a593Smuzhiyun  * @adapter: pointer to adapter struct
556*4882a593Smuzhiyun  * @skb: particular skb to send timestamp with
557*4882a593Smuzhiyun  *
558*4882a593Smuzhiyun  * if the timestamp is valid, we convert it into the timecounter ns
559*4882a593Smuzhiyun  * value, then store that result into the hwtstamps structure which
560*4882a593Smuzhiyun  * is passed up the network stack
561*4882a593Smuzhiyun  */
aq_ptp_rx_hwtstamp(struct aq_ptp_s * aq_ptp,struct sk_buff * skb,u64 timestamp)562*4882a593Smuzhiyun static void aq_ptp_rx_hwtstamp(struct aq_ptp_s *aq_ptp, struct sk_buff *skb,
563*4882a593Smuzhiyun 			       u64 timestamp)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun 	timestamp -= atomic_read(&aq_ptp->offset_ingress);
566*4882a593Smuzhiyun 	aq_ptp_convert_to_hwtstamp(aq_ptp, skb_hwtstamps(skb), timestamp);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun 
aq_ptp_hwtstamp_config_get(struct aq_ptp_s * aq_ptp,struct hwtstamp_config * config)569*4882a593Smuzhiyun void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp,
570*4882a593Smuzhiyun 				struct hwtstamp_config *config)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	*config = aq_ptp->hwtstamp_config;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun 
aq_ptp_prepare_filters(struct aq_ptp_s * aq_ptp)575*4882a593Smuzhiyun static void aq_ptp_prepare_filters(struct aq_ptp_s *aq_ptp)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	aq_ptp->udp_filter.cmd = HW_ATL_RX_ENABLE_FLTR_L3L4 |
578*4882a593Smuzhiyun 			       HW_ATL_RX_ENABLE_CMP_PROT_L4 |
579*4882a593Smuzhiyun 			       HW_ATL_RX_UDP |
580*4882a593Smuzhiyun 			       HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 |
581*4882a593Smuzhiyun 			       HW_ATL_RX_HOST << HW_ATL_RX_ACTION_FL3F4_SHIFT |
582*4882a593Smuzhiyun 			       HW_ATL_RX_ENABLE_QUEUE_L3L4 |
583*4882a593Smuzhiyun 			       aq_ptp->ptp_rx.idx << HW_ATL_RX_QUEUE_FL3L4_SHIFT;
584*4882a593Smuzhiyun 	aq_ptp->udp_filter.p_dst = PTP_EV_PORT;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	aq_ptp->eth_type_filter.ethertype = ETH_P_1588;
587*4882a593Smuzhiyun 	aq_ptp->eth_type_filter.queue = aq_ptp->ptp_rx.idx;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
aq_ptp_hwtstamp_config_set(struct aq_ptp_s * aq_ptp,struct hwtstamp_config * config)590*4882a593Smuzhiyun int aq_ptp_hwtstamp_config_set(struct aq_ptp_s *aq_ptp,
591*4882a593Smuzhiyun 			       struct hwtstamp_config *config)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
594*4882a593Smuzhiyun 	const struct aq_hw_ops *hw_ops;
595*4882a593Smuzhiyun 	int err = 0;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	hw_ops = aq_nic->aq_hw_ops;
598*4882a593Smuzhiyun 	if (config->tx_type == HWTSTAMP_TX_ON ||
599*4882a593Smuzhiyun 	    config->rx_filter == HWTSTAMP_FILTER_PTP_V2_EVENT) {
600*4882a593Smuzhiyun 		aq_ptp_prepare_filters(aq_ptp);
601*4882a593Smuzhiyun 		if (hw_ops->hw_filter_l3l4_set) {
602*4882a593Smuzhiyun 			err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
603*4882a593Smuzhiyun 							 &aq_ptp->udp_filter);
604*4882a593Smuzhiyun 		}
605*4882a593Smuzhiyun 		if (!err && hw_ops->hw_filter_l2_set) {
606*4882a593Smuzhiyun 			err = hw_ops->hw_filter_l2_set(aq_nic->aq_hw,
607*4882a593Smuzhiyun 						       &aq_ptp->eth_type_filter);
608*4882a593Smuzhiyun 		}
609*4882a593Smuzhiyun 		aq_utils_obj_set(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP);
610*4882a593Smuzhiyun 	} else {
611*4882a593Smuzhiyun 		aq_ptp->udp_filter.cmd &= ~HW_ATL_RX_ENABLE_FLTR_L3L4;
612*4882a593Smuzhiyun 		if (hw_ops->hw_filter_l3l4_set) {
613*4882a593Smuzhiyun 			err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
614*4882a593Smuzhiyun 							 &aq_ptp->udp_filter);
615*4882a593Smuzhiyun 		}
616*4882a593Smuzhiyun 		if (!err && hw_ops->hw_filter_l2_clear) {
617*4882a593Smuzhiyun 			err = hw_ops->hw_filter_l2_clear(aq_nic->aq_hw,
618*4882a593Smuzhiyun 							&aq_ptp->eth_type_filter);
619*4882a593Smuzhiyun 		}
620*4882a593Smuzhiyun 		aq_utils_obj_clear(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP);
621*4882a593Smuzhiyun 	}
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (err)
624*4882a593Smuzhiyun 		return -EREMOTEIO;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	aq_ptp->hwtstamp_config = *config;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	return 0;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun 
aq_ptp_ring(struct aq_nic_s * aq_nic,struct aq_ring_s * ring)631*4882a593Smuzhiyun bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	if (!aq_ptp)
636*4882a593Smuzhiyun 		return false;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	return &aq_ptp->ptp_tx == ring ||
639*4882a593Smuzhiyun 	       &aq_ptp->ptp_rx == ring || &aq_ptp->hwts_rx == ring;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
aq_ptp_extract_ts(struct aq_nic_s * aq_nic,struct sk_buff * skb,u8 * p,unsigned int len)642*4882a593Smuzhiyun u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p,
643*4882a593Smuzhiyun 		      unsigned int len)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
646*4882a593Smuzhiyun 	u64 timestamp = 0;
647*4882a593Smuzhiyun 	u16 ret = aq_nic->aq_hw_ops->rx_extract_ts(aq_nic->aq_hw,
648*4882a593Smuzhiyun 						   p, len, &timestamp);
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	if (ret > 0)
651*4882a593Smuzhiyun 		aq_ptp_rx_hwtstamp(aq_ptp, skb, timestamp);
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	return ret;
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun 
aq_ptp_poll(struct napi_struct * napi,int budget)656*4882a593Smuzhiyun static int aq_ptp_poll(struct napi_struct *napi, int budget)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(napi, struct aq_ptp_s, napi);
659*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
660*4882a593Smuzhiyun 	bool was_cleaned = false;
661*4882a593Smuzhiyun 	int work_done = 0;
662*4882a593Smuzhiyun 	int err;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	/* Processing PTP TX traffic */
665*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_tx_head_update(aq_nic->aq_hw,
666*4882a593Smuzhiyun 							&aq_ptp->ptp_tx);
667*4882a593Smuzhiyun 	if (err < 0)
668*4882a593Smuzhiyun 		goto err_exit;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (aq_ptp->ptp_tx.sw_head != aq_ptp->ptp_tx.hw_head) {
671*4882a593Smuzhiyun 		aq_ring_tx_clean(&aq_ptp->ptp_tx);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 		was_cleaned = true;
674*4882a593Smuzhiyun 	}
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	/* Processing HW_TIMESTAMP RX traffic */
677*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_receive(aq_nic->aq_hw,
678*4882a593Smuzhiyun 							 &aq_ptp->hwts_rx);
679*4882a593Smuzhiyun 	if (err < 0)
680*4882a593Smuzhiyun 		goto err_exit;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	if (aq_ptp->hwts_rx.sw_head != aq_ptp->hwts_rx.hw_head) {
683*4882a593Smuzhiyun 		aq_ring_hwts_rx_clean(&aq_ptp->hwts_rx, aq_nic);
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 		err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw,
686*4882a593Smuzhiyun 							      &aq_ptp->hwts_rx);
687*4882a593Smuzhiyun 		if (err < 0)
688*4882a593Smuzhiyun 			goto err_exit;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 		was_cleaned = true;
691*4882a593Smuzhiyun 	}
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	/* Processing PTP RX traffic */
694*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_rx_receive(aq_nic->aq_hw,
695*4882a593Smuzhiyun 						    &aq_ptp->ptp_rx);
696*4882a593Smuzhiyun 	if (err < 0)
697*4882a593Smuzhiyun 		goto err_exit;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	if (aq_ptp->ptp_rx.sw_head != aq_ptp->ptp_rx.hw_head) {
700*4882a593Smuzhiyun 		unsigned int sw_tail_old;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 		err = aq_ring_rx_clean(&aq_ptp->ptp_rx, napi, &work_done, budget);
703*4882a593Smuzhiyun 		if (err < 0)
704*4882a593Smuzhiyun 			goto err_exit;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 		sw_tail_old = aq_ptp->ptp_rx.sw_tail;
707*4882a593Smuzhiyun 		err = aq_ring_rx_fill(&aq_ptp->ptp_rx);
708*4882a593Smuzhiyun 		if (err < 0)
709*4882a593Smuzhiyun 			goto err_exit;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 		err = aq_nic->aq_hw_ops->hw_ring_rx_fill(aq_nic->aq_hw,
712*4882a593Smuzhiyun 							 &aq_ptp->ptp_rx,
713*4882a593Smuzhiyun 							 sw_tail_old);
714*4882a593Smuzhiyun 		if (err < 0)
715*4882a593Smuzhiyun 			goto err_exit;
716*4882a593Smuzhiyun 	}
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	if (was_cleaned)
719*4882a593Smuzhiyun 		work_done = budget;
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	if (work_done < budget) {
722*4882a593Smuzhiyun 		napi_complete_done(napi, work_done);
723*4882a593Smuzhiyun 		aq_nic->aq_hw_ops->hw_irq_enable(aq_nic->aq_hw,
724*4882a593Smuzhiyun 					BIT_ULL(aq_ptp->ptp_ring_param.vec_idx));
725*4882a593Smuzhiyun 	}
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun err_exit:
728*4882a593Smuzhiyun 	return work_done;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
aq_ptp_isr(int irq,void * private)731*4882a593Smuzhiyun static irqreturn_t aq_ptp_isr(int irq, void *private)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = private;
734*4882a593Smuzhiyun 	int err = 0;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	if (!aq_ptp) {
737*4882a593Smuzhiyun 		err = -EINVAL;
738*4882a593Smuzhiyun 		goto err_exit;
739*4882a593Smuzhiyun 	}
740*4882a593Smuzhiyun 	napi_schedule(&aq_ptp->napi);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun err_exit:
743*4882a593Smuzhiyun 	return err >= 0 ? IRQ_HANDLED : IRQ_NONE;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun 
aq_ptp_xmit(struct aq_nic_s * aq_nic,struct sk_buff * skb)746*4882a593Smuzhiyun int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
749*4882a593Smuzhiyun 	struct aq_ring_s *ring = &aq_ptp->ptp_tx;
750*4882a593Smuzhiyun 	unsigned long irq_flags;
751*4882a593Smuzhiyun 	int err = NETDEV_TX_OK;
752*4882a593Smuzhiyun 	unsigned int frags;
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	if (skb->len <= 0) {
755*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
756*4882a593Smuzhiyun 		goto err_exit;
757*4882a593Smuzhiyun 	}
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	frags = skb_shinfo(skb)->nr_frags + 1;
760*4882a593Smuzhiyun 	/* Frags cannot be bigger 16KB
761*4882a593Smuzhiyun 	 * because PTP usually works
762*4882a593Smuzhiyun 	 * without Jumbo even in a background
763*4882a593Smuzhiyun 	 */
764*4882a593Smuzhiyun 	if (frags > AQ_CFG_SKB_FRAGS_MAX || frags > aq_ring_avail_dx(ring)) {
765*4882a593Smuzhiyun 		/* Drop packet because it doesn't make sence to delay it */
766*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
767*4882a593Smuzhiyun 		goto err_exit;
768*4882a593Smuzhiyun 	}
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	err = aq_ptp_skb_put(&aq_ptp->skb_ring, skb);
771*4882a593Smuzhiyun 	if (err) {
772*4882a593Smuzhiyun 		netdev_err(aq_nic->ndev, "SKB Ring is overflow (%u)!\n",
773*4882a593Smuzhiyun 			   ring->size);
774*4882a593Smuzhiyun 		return NETDEV_TX_BUSY;
775*4882a593Smuzhiyun 	}
776*4882a593Smuzhiyun 	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
777*4882a593Smuzhiyun 	aq_ptp_tx_timeout_start(aq_ptp);
778*4882a593Smuzhiyun 	skb_tx_timestamp(skb);
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	spin_lock_irqsave(&aq_nic->aq_ptp->ptp_ring_lock, irq_flags);
781*4882a593Smuzhiyun 	frags = aq_nic_map_skb(aq_nic, skb, ring);
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	if (likely(frags)) {
784*4882a593Smuzhiyun 		err = aq_nic->aq_hw_ops->hw_ring_tx_xmit(aq_nic->aq_hw,
785*4882a593Smuzhiyun 						       ring, frags);
786*4882a593Smuzhiyun 		if (err >= 0) {
787*4882a593Smuzhiyun 			u64_stats_update_begin(&ring->stats.tx.syncp);
788*4882a593Smuzhiyun 			++ring->stats.tx.packets;
789*4882a593Smuzhiyun 			ring->stats.tx.bytes += skb->len;
790*4882a593Smuzhiyun 			u64_stats_update_end(&ring->stats.tx.syncp);
791*4882a593Smuzhiyun 		}
792*4882a593Smuzhiyun 	} else {
793*4882a593Smuzhiyun 		err = NETDEV_TX_BUSY;
794*4882a593Smuzhiyun 	}
795*4882a593Smuzhiyun 	spin_unlock_irqrestore(&aq_nic->aq_ptp->ptp_ring_lock, irq_flags);
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun err_exit:
798*4882a593Smuzhiyun 	return err;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun 
aq_ptp_service_task(struct aq_nic_s * aq_nic)801*4882a593Smuzhiyun void aq_ptp_service_task(struct aq_nic_s *aq_nic)
802*4882a593Smuzhiyun {
803*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	if (!aq_ptp)
806*4882a593Smuzhiyun 		return;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	aq_ptp_tx_timeout_check(aq_ptp);
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun 
aq_ptp_irq_alloc(struct aq_nic_s * aq_nic)811*4882a593Smuzhiyun int aq_ptp_irq_alloc(struct aq_nic_s *aq_nic)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun 	struct pci_dev *pdev = aq_nic->pdev;
814*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
815*4882a593Smuzhiyun 	int err = 0;
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	if (!aq_ptp)
818*4882a593Smuzhiyun 		return 0;
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	if (pdev->msix_enabled || pdev->msi_enabled) {
821*4882a593Smuzhiyun 		err = request_irq(pci_irq_vector(pdev, aq_ptp->idx_vector),
822*4882a593Smuzhiyun 				  aq_ptp_isr, 0, aq_nic->ndev->name, aq_ptp);
823*4882a593Smuzhiyun 	} else {
824*4882a593Smuzhiyun 		err = -EINVAL;
825*4882a593Smuzhiyun 		goto err_exit;
826*4882a593Smuzhiyun 	}
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun err_exit:
829*4882a593Smuzhiyun 	return err;
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun 
aq_ptp_irq_free(struct aq_nic_s * aq_nic)832*4882a593Smuzhiyun void aq_ptp_irq_free(struct aq_nic_s *aq_nic)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
835*4882a593Smuzhiyun 	struct pci_dev *pdev = aq_nic->pdev;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	if (!aq_ptp)
838*4882a593Smuzhiyun 		return;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	free_irq(pci_irq_vector(pdev, aq_ptp->idx_vector), aq_ptp);
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun 
aq_ptp_ring_init(struct aq_nic_s * aq_nic)843*4882a593Smuzhiyun int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
846*4882a593Smuzhiyun 	int err = 0;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	if (!aq_ptp)
849*4882a593Smuzhiyun 		return 0;
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	err = aq_ring_init(&aq_ptp->ptp_tx, ATL_RING_TX);
852*4882a593Smuzhiyun 	if (err < 0)
853*4882a593Smuzhiyun 		goto err_exit;
854*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_tx_init(aq_nic->aq_hw,
855*4882a593Smuzhiyun 						 &aq_ptp->ptp_tx,
856*4882a593Smuzhiyun 						 &aq_ptp->ptp_ring_param);
857*4882a593Smuzhiyun 	if (err < 0)
858*4882a593Smuzhiyun 		goto err_exit;
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	err = aq_ring_init(&aq_ptp->ptp_rx, ATL_RING_RX);
861*4882a593Smuzhiyun 	if (err < 0)
862*4882a593Smuzhiyun 		goto err_exit;
863*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw,
864*4882a593Smuzhiyun 						 &aq_ptp->ptp_rx,
865*4882a593Smuzhiyun 						 &aq_ptp->ptp_ring_param);
866*4882a593Smuzhiyun 	if (err < 0)
867*4882a593Smuzhiyun 		goto err_exit;
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 	err = aq_ring_rx_fill(&aq_ptp->ptp_rx);
870*4882a593Smuzhiyun 	if (err < 0)
871*4882a593Smuzhiyun 		goto err_rx_free;
872*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_rx_fill(aq_nic->aq_hw,
873*4882a593Smuzhiyun 						 &aq_ptp->ptp_rx,
874*4882a593Smuzhiyun 						 0U);
875*4882a593Smuzhiyun 	if (err < 0)
876*4882a593Smuzhiyun 		goto err_rx_free;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	err = aq_ring_init(&aq_ptp->hwts_rx, ATL_RING_RX);
879*4882a593Smuzhiyun 	if (err < 0)
880*4882a593Smuzhiyun 		goto err_rx_free;
881*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw,
882*4882a593Smuzhiyun 						 &aq_ptp->hwts_rx,
883*4882a593Smuzhiyun 						 &aq_ptp->ptp_ring_param);
884*4882a593Smuzhiyun 	if (err < 0)
885*4882a593Smuzhiyun 		goto err_exit;
886*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw,
887*4882a593Smuzhiyun 						      &aq_ptp->hwts_rx);
888*4882a593Smuzhiyun 	if (err < 0)
889*4882a593Smuzhiyun 		goto err_exit;
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 	return err;
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun err_rx_free:
894*4882a593Smuzhiyun 	aq_ring_rx_deinit(&aq_ptp->ptp_rx);
895*4882a593Smuzhiyun err_exit:
896*4882a593Smuzhiyun 	return err;
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun 
aq_ptp_ring_start(struct aq_nic_s * aq_nic)899*4882a593Smuzhiyun int aq_ptp_ring_start(struct aq_nic_s *aq_nic)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
902*4882a593Smuzhiyun 	int err = 0;
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	if (!aq_ptp)
905*4882a593Smuzhiyun 		return 0;
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_tx_start(aq_nic->aq_hw, &aq_ptp->ptp_tx);
908*4882a593Smuzhiyun 	if (err < 0)
909*4882a593Smuzhiyun 		goto err_exit;
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw, &aq_ptp->ptp_rx);
912*4882a593Smuzhiyun 	if (err < 0)
913*4882a593Smuzhiyun 		goto err_exit;
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw,
916*4882a593Smuzhiyun 						  &aq_ptp->hwts_rx);
917*4882a593Smuzhiyun 	if (err < 0)
918*4882a593Smuzhiyun 		goto err_exit;
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	napi_enable(&aq_ptp->napi);
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun err_exit:
923*4882a593Smuzhiyun 	return err;
924*4882a593Smuzhiyun }
925*4882a593Smuzhiyun 
aq_ptp_ring_stop(struct aq_nic_s * aq_nic)926*4882a593Smuzhiyun void aq_ptp_ring_stop(struct aq_nic_s *aq_nic)
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	if (!aq_ptp)
931*4882a593Smuzhiyun 		return;
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_ring_tx_stop(aq_nic->aq_hw, &aq_ptp->ptp_tx);
934*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->ptp_rx);
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->hwts_rx);
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 	napi_disable(&aq_ptp->napi);
939*4882a593Smuzhiyun }
940*4882a593Smuzhiyun 
aq_ptp_ring_deinit(struct aq_nic_s * aq_nic)941*4882a593Smuzhiyun void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic)
942*4882a593Smuzhiyun {
943*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	if (!aq_ptp || !aq_ptp->ptp_tx.aq_nic || !aq_ptp->ptp_rx.aq_nic)
946*4882a593Smuzhiyun 		return;
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	aq_ring_tx_clean(&aq_ptp->ptp_tx);
949*4882a593Smuzhiyun 	aq_ring_rx_deinit(&aq_ptp->ptp_rx);
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun 
aq_ptp_ring_alloc(struct aq_nic_s * aq_nic)952*4882a593Smuzhiyun int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
955*4882a593Smuzhiyun 	unsigned int tx_ring_idx, rx_ring_idx;
956*4882a593Smuzhiyun 	struct aq_ring_s *hwts;
957*4882a593Smuzhiyun 	struct aq_ring_s *ring;
958*4882a593Smuzhiyun 	int err;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 	if (!aq_ptp)
961*4882a593Smuzhiyun 		return 0;
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	tx_ring_idx = aq_ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode);
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 	ring = aq_ring_tx_alloc(&aq_ptp->ptp_tx, aq_nic,
966*4882a593Smuzhiyun 				tx_ring_idx, &aq_nic->aq_nic_cfg);
967*4882a593Smuzhiyun 	if (!ring) {
968*4882a593Smuzhiyun 		err = -ENOMEM;
969*4882a593Smuzhiyun 		goto err_exit;
970*4882a593Smuzhiyun 	}
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	rx_ring_idx = aq_ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode);
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	ring = aq_ring_rx_alloc(&aq_ptp->ptp_rx, aq_nic,
975*4882a593Smuzhiyun 				rx_ring_idx, &aq_nic->aq_nic_cfg);
976*4882a593Smuzhiyun 	if (!ring) {
977*4882a593Smuzhiyun 		err = -ENOMEM;
978*4882a593Smuzhiyun 		goto err_exit_ptp_tx;
979*4882a593Smuzhiyun 	}
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	hwts = aq_ring_hwts_rx_alloc(&aq_ptp->hwts_rx, aq_nic, PTP_HWST_RING_IDX,
982*4882a593Smuzhiyun 				     aq_nic->aq_nic_cfg.rxds,
983*4882a593Smuzhiyun 				     aq_nic->aq_nic_cfg.aq_hw_caps->rxd_size);
984*4882a593Smuzhiyun 	if (!hwts) {
985*4882a593Smuzhiyun 		err = -ENOMEM;
986*4882a593Smuzhiyun 		goto err_exit_ptp_rx;
987*4882a593Smuzhiyun 	}
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	err = aq_ptp_skb_ring_init(&aq_ptp->skb_ring, aq_nic->aq_nic_cfg.rxds);
990*4882a593Smuzhiyun 	if (err != 0) {
991*4882a593Smuzhiyun 		err = -ENOMEM;
992*4882a593Smuzhiyun 		goto err_exit_hwts_rx;
993*4882a593Smuzhiyun 	}
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	aq_ptp->ptp_ring_param.vec_idx = aq_ptp->idx_vector;
996*4882a593Smuzhiyun 	aq_ptp->ptp_ring_param.cpu = aq_ptp->ptp_ring_param.vec_idx +
997*4882a593Smuzhiyun 			aq_nic_get_cfg(aq_nic)->aq_rss.base_cpu_number;
998*4882a593Smuzhiyun 	cpumask_set_cpu(aq_ptp->ptp_ring_param.cpu,
999*4882a593Smuzhiyun 			&aq_ptp->ptp_ring_param.affinity_mask);
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun 	return 0;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun err_exit_hwts_rx:
1004*4882a593Smuzhiyun 	aq_ring_free(&aq_ptp->hwts_rx);
1005*4882a593Smuzhiyun err_exit_ptp_rx:
1006*4882a593Smuzhiyun 	aq_ring_free(&aq_ptp->ptp_rx);
1007*4882a593Smuzhiyun err_exit_ptp_tx:
1008*4882a593Smuzhiyun 	aq_ring_free(&aq_ptp->ptp_tx);
1009*4882a593Smuzhiyun err_exit:
1010*4882a593Smuzhiyun 	return err;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun 
aq_ptp_ring_free(struct aq_nic_s * aq_nic)1013*4882a593Smuzhiyun void aq_ptp_ring_free(struct aq_nic_s *aq_nic)
1014*4882a593Smuzhiyun {
1015*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	if (!aq_ptp)
1018*4882a593Smuzhiyun 		return;
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 	aq_ring_free(&aq_ptp->ptp_tx);
1021*4882a593Smuzhiyun 	aq_ring_free(&aq_ptp->ptp_rx);
1022*4882a593Smuzhiyun 	aq_ring_free(&aq_ptp->hwts_rx);
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	aq_ptp_skb_ring_release(&aq_ptp->skb_ring);
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun #define MAX_PTP_GPIO_COUNT 4
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun static struct ptp_clock_info aq_ptp_clock = {
1030*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
1031*4882a593Smuzhiyun 	.name		= "atlantic ptp",
1032*4882a593Smuzhiyun 	.max_adj	= 999999999,
1033*4882a593Smuzhiyun 	.n_ext_ts	= 0,
1034*4882a593Smuzhiyun 	.pps		= 0,
1035*4882a593Smuzhiyun 	.adjfine	= aq_ptp_adjfine,
1036*4882a593Smuzhiyun 	.adjtime	= aq_ptp_adjtime,
1037*4882a593Smuzhiyun 	.gettime64	= aq_ptp_gettime,
1038*4882a593Smuzhiyun 	.settime64	= aq_ptp_settime,
1039*4882a593Smuzhiyun 	.n_per_out	= 0,
1040*4882a593Smuzhiyun 	.enable		= aq_ptp_gpio_feature_enable,
1041*4882a593Smuzhiyun 	.n_pins		= 0,
1042*4882a593Smuzhiyun 	.verify		= aq_ptp_verify,
1043*4882a593Smuzhiyun 	.pin_config	= NULL,
1044*4882a593Smuzhiyun };
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun #define ptp_offset_init(__idx, __mbps, __egress, __ingress)   do { \
1047*4882a593Smuzhiyun 		ptp_offset[__idx].mbps = (__mbps); \
1048*4882a593Smuzhiyun 		ptp_offset[__idx].egress = (__egress); \
1049*4882a593Smuzhiyun 		ptp_offset[__idx].ingress = (__ingress); } \
1050*4882a593Smuzhiyun 		while (0)
1051*4882a593Smuzhiyun 
aq_ptp_offset_init_from_fw(const struct hw_atl_ptp_offset * offsets)1052*4882a593Smuzhiyun static void aq_ptp_offset_init_from_fw(const struct hw_atl_ptp_offset *offsets)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun 	int i;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	/* Load offsets for PTP */
1057*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ptp_offset); i++) {
1058*4882a593Smuzhiyun 		switch (i) {
1059*4882a593Smuzhiyun 		/* 100M */
1060*4882a593Smuzhiyun 		case ptp_offset_idx_100:
1061*4882a593Smuzhiyun 			ptp_offset_init(i, 100,
1062*4882a593Smuzhiyun 					offsets->egress_100,
1063*4882a593Smuzhiyun 					offsets->ingress_100);
1064*4882a593Smuzhiyun 			break;
1065*4882a593Smuzhiyun 		/* 1G */
1066*4882a593Smuzhiyun 		case ptp_offset_idx_1000:
1067*4882a593Smuzhiyun 			ptp_offset_init(i, 1000,
1068*4882a593Smuzhiyun 					offsets->egress_1000,
1069*4882a593Smuzhiyun 					offsets->ingress_1000);
1070*4882a593Smuzhiyun 			break;
1071*4882a593Smuzhiyun 		/* 2.5G */
1072*4882a593Smuzhiyun 		case ptp_offset_idx_2500:
1073*4882a593Smuzhiyun 			ptp_offset_init(i, 2500,
1074*4882a593Smuzhiyun 					offsets->egress_2500,
1075*4882a593Smuzhiyun 					offsets->ingress_2500);
1076*4882a593Smuzhiyun 			break;
1077*4882a593Smuzhiyun 		/* 5G */
1078*4882a593Smuzhiyun 		case ptp_offset_idx_5000:
1079*4882a593Smuzhiyun 			ptp_offset_init(i, 5000,
1080*4882a593Smuzhiyun 					offsets->egress_5000,
1081*4882a593Smuzhiyun 					offsets->ingress_5000);
1082*4882a593Smuzhiyun 			break;
1083*4882a593Smuzhiyun 		/* 10G */
1084*4882a593Smuzhiyun 		case ptp_offset_idx_10000:
1085*4882a593Smuzhiyun 			ptp_offset_init(i, 10000,
1086*4882a593Smuzhiyun 					offsets->egress_10000,
1087*4882a593Smuzhiyun 					offsets->ingress_10000);
1088*4882a593Smuzhiyun 			break;
1089*4882a593Smuzhiyun 		}
1090*4882a593Smuzhiyun 	}
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun 
aq_ptp_offset_init(const struct hw_atl_ptp_offset * offsets)1093*4882a593Smuzhiyun static void aq_ptp_offset_init(const struct hw_atl_ptp_offset *offsets)
1094*4882a593Smuzhiyun {
1095*4882a593Smuzhiyun 	memset(ptp_offset, 0, sizeof(ptp_offset));
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	aq_ptp_offset_init_from_fw(offsets);
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun 
aq_ptp_gpio_init(struct ptp_clock_info * info,struct hw_atl_info * hw_info)1100*4882a593Smuzhiyun static void aq_ptp_gpio_init(struct ptp_clock_info *info,
1101*4882a593Smuzhiyun 			     struct hw_atl_info *hw_info)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun 	struct ptp_pin_desc pin_desc[MAX_PTP_GPIO_COUNT];
1104*4882a593Smuzhiyun 	u32 extts_pin_cnt = 0;
1105*4882a593Smuzhiyun 	u32 out_pin_cnt = 0;
1106*4882a593Smuzhiyun 	u32 i;
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun 	memset(pin_desc, 0, sizeof(pin_desc));
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	for (i = 0; i < MAX_PTP_GPIO_COUNT - 1; i++) {
1111*4882a593Smuzhiyun 		if (hw_info->gpio_pin[i] ==
1112*4882a593Smuzhiyun 		    (GPIO_PIN_FUNCTION_PTP0 + out_pin_cnt)) {
1113*4882a593Smuzhiyun 			snprintf(pin_desc[out_pin_cnt].name,
1114*4882a593Smuzhiyun 				 sizeof(pin_desc[out_pin_cnt].name),
1115*4882a593Smuzhiyun 				 "AQ_GPIO%d", i);
1116*4882a593Smuzhiyun 			pin_desc[out_pin_cnt].index = out_pin_cnt;
1117*4882a593Smuzhiyun 			pin_desc[out_pin_cnt].chan = out_pin_cnt;
1118*4882a593Smuzhiyun 			pin_desc[out_pin_cnt++].func = PTP_PF_PEROUT;
1119*4882a593Smuzhiyun 		}
1120*4882a593Smuzhiyun 	}
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun 	info->n_per_out = out_pin_cnt;
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun 	if (hw_info->caps_ex & BIT(CAPS_EX_PHY_CTRL_TS_PIN)) {
1125*4882a593Smuzhiyun 		extts_pin_cnt += 1;
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 		snprintf(pin_desc[out_pin_cnt].name,
1128*4882a593Smuzhiyun 			 sizeof(pin_desc[out_pin_cnt].name),
1129*4882a593Smuzhiyun 			  "AQ_GPIO%d", out_pin_cnt);
1130*4882a593Smuzhiyun 		pin_desc[out_pin_cnt].index = out_pin_cnt;
1131*4882a593Smuzhiyun 		pin_desc[out_pin_cnt].chan = 0;
1132*4882a593Smuzhiyun 		pin_desc[out_pin_cnt].func = PTP_PF_EXTTS;
1133*4882a593Smuzhiyun 	}
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 	info->n_pins = out_pin_cnt + extts_pin_cnt;
1136*4882a593Smuzhiyun 	info->n_ext_ts = extts_pin_cnt;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 	if (!info->n_pins)
1139*4882a593Smuzhiyun 		return;
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	info->pin_config = kcalloc(info->n_pins, sizeof(struct ptp_pin_desc),
1142*4882a593Smuzhiyun 				   GFP_KERNEL);
1143*4882a593Smuzhiyun 
1144*4882a593Smuzhiyun 	if (!info->pin_config)
1145*4882a593Smuzhiyun 		return;
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun 	memcpy(info->pin_config, &pin_desc,
1148*4882a593Smuzhiyun 	       sizeof(struct ptp_pin_desc) * info->n_pins);
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun 
aq_ptp_clock_init(struct aq_nic_s * aq_nic)1151*4882a593Smuzhiyun void aq_ptp_clock_init(struct aq_nic_s *aq_nic)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
1154*4882a593Smuzhiyun 	struct timespec64 ts;
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun 	ktime_get_real_ts64(&ts);
1157*4882a593Smuzhiyun 	aq_ptp_settime(&aq_ptp->ptp_info, &ts);
1158*4882a593Smuzhiyun }
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun static void aq_ptp_poll_sync_work_cb(struct work_struct *w);
1161*4882a593Smuzhiyun 
aq_ptp_init(struct aq_nic_s * aq_nic,unsigned int idx_vec)1162*4882a593Smuzhiyun int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
1163*4882a593Smuzhiyun {
1164*4882a593Smuzhiyun 	bool a1_ptp = ATL_HW_IS_CHIP_FEATURE(aq_nic->aq_hw, ATLANTIC);
1165*4882a593Smuzhiyun 	struct hw_atl_utils_mbox mbox;
1166*4882a593Smuzhiyun 	struct ptp_clock *clock;
1167*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp;
1168*4882a593Smuzhiyun 	int err = 0;
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	if (!a1_ptp) {
1171*4882a593Smuzhiyun 		aq_nic->aq_ptp = NULL;
1172*4882a593Smuzhiyun 		return 0;
1173*4882a593Smuzhiyun 	}
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 	if (!aq_nic->aq_hw_ops->hw_get_ptp_ts) {
1176*4882a593Smuzhiyun 		aq_nic->aq_ptp = NULL;
1177*4882a593Smuzhiyun 		return 0;
1178*4882a593Smuzhiyun 	}
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	if (!aq_nic->aq_fw_ops->enable_ptp) {
1181*4882a593Smuzhiyun 		aq_nic->aq_ptp = NULL;
1182*4882a593Smuzhiyun 		return 0;
1183*4882a593Smuzhiyun 	}
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun 	hw_atl_utils_mpi_read_stats(aq_nic->aq_hw, &mbox);
1186*4882a593Smuzhiyun 
1187*4882a593Smuzhiyun 	if (!(mbox.info.caps_ex & BIT(CAPS_EX_PHY_PTP_EN))) {
1188*4882a593Smuzhiyun 		aq_nic->aq_ptp = NULL;
1189*4882a593Smuzhiyun 		return 0;
1190*4882a593Smuzhiyun 	}
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 	aq_ptp_offset_init(&mbox.info.ptp_offset);
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	aq_ptp = kzalloc(sizeof(*aq_ptp), GFP_KERNEL);
1195*4882a593Smuzhiyun 	if (!aq_ptp) {
1196*4882a593Smuzhiyun 		err = -ENOMEM;
1197*4882a593Smuzhiyun 		goto err_exit;
1198*4882a593Smuzhiyun 	}
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	aq_ptp->aq_nic = aq_nic;
1201*4882a593Smuzhiyun 	aq_ptp->a1_ptp = a1_ptp;
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	spin_lock_init(&aq_ptp->ptp_lock);
1204*4882a593Smuzhiyun 	spin_lock_init(&aq_ptp->ptp_ring_lock);
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 	aq_ptp->ptp_info = aq_ptp_clock;
1207*4882a593Smuzhiyun 	aq_ptp_gpio_init(&aq_ptp->ptp_info, &mbox.info);
1208*4882a593Smuzhiyun 	clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev);
1209*4882a593Smuzhiyun 	if (IS_ERR(clock)) {
1210*4882a593Smuzhiyun 		netdev_err(aq_nic->ndev, "ptp_clock_register failed\n");
1211*4882a593Smuzhiyun 		err = PTR_ERR(clock);
1212*4882a593Smuzhiyun 		goto err_exit;
1213*4882a593Smuzhiyun 	}
1214*4882a593Smuzhiyun 	aq_ptp->ptp_clock = clock;
1215*4882a593Smuzhiyun 	aq_ptp_tx_timeout_init(&aq_ptp->ptp_tx_timeout);
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun 	atomic_set(&aq_ptp->offset_egress, 0);
1218*4882a593Smuzhiyun 	atomic_set(&aq_ptp->offset_ingress, 0);
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	netif_napi_add(aq_nic_get_ndev(aq_nic), &aq_ptp->napi,
1221*4882a593Smuzhiyun 		       aq_ptp_poll, AQ_CFG_NAPI_WEIGHT);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	aq_ptp->idx_vector = idx_vec;
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 	aq_nic->aq_ptp = aq_ptp;
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun 	/* enable ptp counter */
1228*4882a593Smuzhiyun 	aq_utils_obj_set(&aq_nic->aq_hw->flags, AQ_HW_PTP_AVAILABLE);
1229*4882a593Smuzhiyun 	mutex_lock(&aq_nic->fwreq_mutex);
1230*4882a593Smuzhiyun 	aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 1);
1231*4882a593Smuzhiyun 	aq_ptp_clock_init(aq_nic);
1232*4882a593Smuzhiyun 	mutex_unlock(&aq_nic->fwreq_mutex);
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&aq_ptp->poll_sync, &aq_ptp_poll_sync_work_cb);
1235*4882a593Smuzhiyun 	aq_ptp->eth_type_filter.location =
1236*4882a593Smuzhiyun 			aq_nic_reserve_filter(aq_nic, aq_rx_filter_ethertype);
1237*4882a593Smuzhiyun 	aq_ptp->udp_filter.location =
1238*4882a593Smuzhiyun 			aq_nic_reserve_filter(aq_nic, aq_rx_filter_l3l4);
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	return 0;
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun err_exit:
1243*4882a593Smuzhiyun 	if (aq_ptp)
1244*4882a593Smuzhiyun 		kfree(aq_ptp->ptp_info.pin_config);
1245*4882a593Smuzhiyun 	kfree(aq_ptp);
1246*4882a593Smuzhiyun 	aq_nic->aq_ptp = NULL;
1247*4882a593Smuzhiyun 	return err;
1248*4882a593Smuzhiyun }
1249*4882a593Smuzhiyun 
aq_ptp_unregister(struct aq_nic_s * aq_nic)1250*4882a593Smuzhiyun void aq_ptp_unregister(struct aq_nic_s *aq_nic)
1251*4882a593Smuzhiyun {
1252*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	if (!aq_ptp)
1255*4882a593Smuzhiyun 		return;
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	ptp_clock_unregister(aq_ptp->ptp_clock);
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun 
aq_ptp_free(struct aq_nic_s * aq_nic)1260*4882a593Smuzhiyun void aq_ptp_free(struct aq_nic_s *aq_nic)
1261*4882a593Smuzhiyun {
1262*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
1263*4882a593Smuzhiyun 
1264*4882a593Smuzhiyun 	if (!aq_ptp)
1265*4882a593Smuzhiyun 		return;
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 	aq_nic_release_filter(aq_nic, aq_rx_filter_ethertype,
1268*4882a593Smuzhiyun 			      aq_ptp->eth_type_filter.location);
1269*4882a593Smuzhiyun 	aq_nic_release_filter(aq_nic, aq_rx_filter_l3l4,
1270*4882a593Smuzhiyun 			      aq_ptp->udp_filter.location);
1271*4882a593Smuzhiyun 	cancel_delayed_work_sync(&aq_ptp->poll_sync);
1272*4882a593Smuzhiyun 	/* disable ptp */
1273*4882a593Smuzhiyun 	mutex_lock(&aq_nic->fwreq_mutex);
1274*4882a593Smuzhiyun 	aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0);
1275*4882a593Smuzhiyun 	mutex_unlock(&aq_nic->fwreq_mutex);
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun 	kfree(aq_ptp->ptp_info.pin_config);
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	netif_napi_del(&aq_ptp->napi);
1280*4882a593Smuzhiyun 	kfree(aq_ptp);
1281*4882a593Smuzhiyun 	aq_nic->aq_ptp = NULL;
1282*4882a593Smuzhiyun }
1283*4882a593Smuzhiyun 
aq_ptp_get_ptp_clock(struct aq_ptp_s * aq_ptp)1284*4882a593Smuzhiyun struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp)
1285*4882a593Smuzhiyun {
1286*4882a593Smuzhiyun 	return aq_ptp->ptp_clock;
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun 
1289*4882a593Smuzhiyun /* PTP external GPIO nanoseconds count */
aq_ptp_get_sync1588_ts(struct aq_nic_s * aq_nic)1290*4882a593Smuzhiyun static uint64_t aq_ptp_get_sync1588_ts(struct aq_nic_s *aq_nic)
1291*4882a593Smuzhiyun {
1292*4882a593Smuzhiyun 	u64 ts = 0;
1293*4882a593Smuzhiyun 
1294*4882a593Smuzhiyun 	if (aq_nic->aq_hw_ops->hw_get_sync_ts)
1295*4882a593Smuzhiyun 		aq_nic->aq_hw_ops->hw_get_sync_ts(aq_nic->aq_hw, &ts);
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	return ts;
1298*4882a593Smuzhiyun }
1299*4882a593Smuzhiyun 
aq_ptp_start_work(struct aq_ptp_s * aq_ptp)1300*4882a593Smuzhiyun static void aq_ptp_start_work(struct aq_ptp_s *aq_ptp)
1301*4882a593Smuzhiyun {
1302*4882a593Smuzhiyun 	if (aq_ptp->extts_pin_enabled) {
1303*4882a593Smuzhiyun 		aq_ptp->poll_timeout_ms = POLL_SYNC_TIMER_MS;
1304*4882a593Smuzhiyun 		aq_ptp->last_sync1588_ts =
1305*4882a593Smuzhiyun 				aq_ptp_get_sync1588_ts(aq_ptp->aq_nic);
1306*4882a593Smuzhiyun 		schedule_delayed_work(&aq_ptp->poll_sync,
1307*4882a593Smuzhiyun 				      msecs_to_jiffies(aq_ptp->poll_timeout_ms));
1308*4882a593Smuzhiyun 	}
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun 
aq_ptp_link_change(struct aq_nic_s * aq_nic)1311*4882a593Smuzhiyun int aq_ptp_link_change(struct aq_nic_s *aq_nic)
1312*4882a593Smuzhiyun {
1313*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun 	if (!aq_ptp)
1316*4882a593Smuzhiyun 		return 0;
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun 	if (aq_nic->aq_hw->aq_link_status.mbps)
1319*4882a593Smuzhiyun 		aq_ptp_start_work(aq_ptp);
1320*4882a593Smuzhiyun 	else
1321*4882a593Smuzhiyun 		cancel_delayed_work_sync(&aq_ptp->poll_sync);
1322*4882a593Smuzhiyun 
1323*4882a593Smuzhiyun 	return 0;
1324*4882a593Smuzhiyun }
1325*4882a593Smuzhiyun 
aq_ptp_sync_ts_updated(struct aq_ptp_s * aq_ptp,u64 * new_ts)1326*4882a593Smuzhiyun static bool aq_ptp_sync_ts_updated(struct aq_ptp_s *aq_ptp, u64 *new_ts)
1327*4882a593Smuzhiyun {
1328*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
1329*4882a593Smuzhiyun 	u64 sync_ts2;
1330*4882a593Smuzhiyun 	u64 sync_ts;
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 	sync_ts = aq_ptp_get_sync1588_ts(aq_nic);
1333*4882a593Smuzhiyun 
1334*4882a593Smuzhiyun 	if (sync_ts != aq_ptp->last_sync1588_ts) {
1335*4882a593Smuzhiyun 		sync_ts2 = aq_ptp_get_sync1588_ts(aq_nic);
1336*4882a593Smuzhiyun 		if (sync_ts != sync_ts2) {
1337*4882a593Smuzhiyun 			sync_ts = sync_ts2;
1338*4882a593Smuzhiyun 			sync_ts2 = aq_ptp_get_sync1588_ts(aq_nic);
1339*4882a593Smuzhiyun 			if (sync_ts != sync_ts2) {
1340*4882a593Smuzhiyun 				netdev_err(aq_nic->ndev,
1341*4882a593Smuzhiyun 					   "%s: Unable to get correct GPIO TS",
1342*4882a593Smuzhiyun 					   __func__);
1343*4882a593Smuzhiyun 				sync_ts = 0;
1344*4882a593Smuzhiyun 			}
1345*4882a593Smuzhiyun 		}
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 		*new_ts = sync_ts;
1348*4882a593Smuzhiyun 		return true;
1349*4882a593Smuzhiyun 	}
1350*4882a593Smuzhiyun 	return false;
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun 
aq_ptp_check_sync1588(struct aq_ptp_s * aq_ptp)1353*4882a593Smuzhiyun static int aq_ptp_check_sync1588(struct aq_ptp_s *aq_ptp)
1354*4882a593Smuzhiyun {
1355*4882a593Smuzhiyun 	struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
1356*4882a593Smuzhiyun 	u64 sync_ts;
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun 	 /* Sync1588 pin was triggered */
1359*4882a593Smuzhiyun 	if (aq_ptp_sync_ts_updated(aq_ptp, &sync_ts)) {
1360*4882a593Smuzhiyun 		if (aq_ptp->extts_pin_enabled) {
1361*4882a593Smuzhiyun 			struct ptp_clock_event ptp_event;
1362*4882a593Smuzhiyun 			u64 time = 0;
1363*4882a593Smuzhiyun 
1364*4882a593Smuzhiyun 			aq_nic->aq_hw_ops->hw_ts_to_sys_clock(aq_nic->aq_hw,
1365*4882a593Smuzhiyun 							      sync_ts, &time);
1366*4882a593Smuzhiyun 			ptp_event.index = aq_ptp->ptp_info.n_pins - 1;
1367*4882a593Smuzhiyun 			ptp_event.timestamp = time;
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun 			ptp_event.type = PTP_CLOCK_EXTTS;
1370*4882a593Smuzhiyun 			ptp_clock_event(aq_ptp->ptp_clock, &ptp_event);
1371*4882a593Smuzhiyun 		}
1372*4882a593Smuzhiyun 
1373*4882a593Smuzhiyun 		aq_ptp->last_sync1588_ts = sync_ts;
1374*4882a593Smuzhiyun 	}
1375*4882a593Smuzhiyun 
1376*4882a593Smuzhiyun 	return 0;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun 
aq_ptp_poll_sync_work_cb(struct work_struct * w)1379*4882a593Smuzhiyun static void aq_ptp_poll_sync_work_cb(struct work_struct *w)
1380*4882a593Smuzhiyun {
1381*4882a593Smuzhiyun 	struct delayed_work *dw = to_delayed_work(w);
1382*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = container_of(dw, struct aq_ptp_s, poll_sync);
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	aq_ptp_check_sync1588(aq_ptp);
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 	if (aq_ptp->extts_pin_enabled) {
1387*4882a593Smuzhiyun 		unsigned long timeout = msecs_to_jiffies(aq_ptp->poll_timeout_ms);
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun 		schedule_delayed_work(&aq_ptp->poll_sync, timeout);
1390*4882a593Smuzhiyun 	}
1391*4882a593Smuzhiyun }
1392*4882a593Smuzhiyun 
aq_ptp_get_ring_cnt(struct aq_nic_s * aq_nic,const enum atl_ring_type ring_type)1393*4882a593Smuzhiyun int aq_ptp_get_ring_cnt(struct aq_nic_s *aq_nic, const enum atl_ring_type ring_type)
1394*4882a593Smuzhiyun {
1395*4882a593Smuzhiyun 	if (!aq_nic->aq_ptp)
1396*4882a593Smuzhiyun 		return 0;
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	/* Additional RX ring is allocated for PTP HWTS on A1 */
1399*4882a593Smuzhiyun 	return (aq_nic->aq_ptp->a1_ptp && ring_type == ATL_RING_RX) ? 2 : 1;
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun 
aq_ptp_get_stats(struct aq_nic_s * aq_nic,u64 * data)1402*4882a593Smuzhiyun u64 *aq_ptp_get_stats(struct aq_nic_s *aq_nic, u64 *data)
1403*4882a593Smuzhiyun {
1404*4882a593Smuzhiyun 	struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
1405*4882a593Smuzhiyun 	unsigned int count = 0U;
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	if (!aq_ptp)
1408*4882a593Smuzhiyun 		return data;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	count = aq_ring_fill_stats_data(&aq_ptp->ptp_rx, data);
1411*4882a593Smuzhiyun 	data += count;
1412*4882a593Smuzhiyun 	count = aq_ring_fill_stats_data(&aq_ptp->ptp_tx, data);
1413*4882a593Smuzhiyun 	data += count;
1414*4882a593Smuzhiyun 
1415*4882a593Smuzhiyun 	if (aq_ptp->a1_ptp) {
1416*4882a593Smuzhiyun 		/* Only Receive ring for HWTS */
1417*4882a593Smuzhiyun 		count = aq_ring_fill_stats_data(&aq_ptp->hwts_rx, data);
1418*4882a593Smuzhiyun 		data += count;
1419*4882a593Smuzhiyun 	}
1420*4882a593Smuzhiyun 
1421*4882a593Smuzhiyun 	return data;
1422*4882a593Smuzhiyun }
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun #endif
1425