1c9c12d33SAleksey Makarov // SPDX-License-Identifier: GPL-2.0
2cb0e3ec4SSunil Goutham /* Marvell RVU Ethernet driver
3c9c12d33SAleksey Makarov  *
4cb0e3ec4SSunil Goutham  * Copyright (C) 2020 Marvell.
5cb0e3ec4SSunil Goutham  *
6c9c12d33SAleksey Makarov  */
7c9c12d33SAleksey Makarov 
88581fd40SJakub Kicinski #include <linux/module.h>
98581fd40SJakub Kicinski 
10c9c12d33SAleksey Makarov #include "otx2_common.h"
11c9c12d33SAleksey Makarov #include "otx2_ptp.h"
12c9c12d33SAleksey Makarov 
is_tstmp_atomic_update_supported(struct otx2_ptp * ptp)13*bdf79b12SSai Krishna static bool is_tstmp_atomic_update_supported(struct otx2_ptp *ptp)
14*bdf79b12SSai Krishna {
15*bdf79b12SSai Krishna 	struct ptp_get_cap_rsp *rsp;
16*bdf79b12SSai Krishna 	struct msg_req *req;
17*bdf79b12SSai Krishna 	int err;
18*bdf79b12SSai Krishna 
19*bdf79b12SSai Krishna 	if (!ptp->nic)
20*bdf79b12SSai Krishna 		return false;
21*bdf79b12SSai Krishna 
22*bdf79b12SSai Krishna 	mutex_lock(&ptp->nic->mbox.lock);
23*bdf79b12SSai Krishna 	req = otx2_mbox_alloc_msg_ptp_get_cap(&ptp->nic->mbox);
24*bdf79b12SSai Krishna 	if (!req) {
25*bdf79b12SSai Krishna 		mutex_unlock(&ptp->nic->mbox.lock);
26*bdf79b12SSai Krishna 		return false;
27*bdf79b12SSai Krishna 	}
28*bdf79b12SSai Krishna 
29*bdf79b12SSai Krishna 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
30*bdf79b12SSai Krishna 	if (err) {
31*bdf79b12SSai Krishna 		mutex_unlock(&ptp->nic->mbox.lock);
32*bdf79b12SSai Krishna 		return false;
33*bdf79b12SSai Krishna 	}
34*bdf79b12SSai Krishna 	rsp = (struct ptp_get_cap_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
35*bdf79b12SSai Krishna 							  &req->hdr);
36*bdf79b12SSai Krishna 	mutex_unlock(&ptp->nic->mbox.lock);
37*bdf79b12SSai Krishna 
38*bdf79b12SSai Krishna 	if (IS_ERR(rsp))
39*bdf79b12SSai Krishna 		return false;
40*bdf79b12SSai Krishna 
41*bdf79b12SSai Krishna 	if (rsp->cap & PTP_CAP_HW_ATOMIC_UPDATE)
42*bdf79b12SSai Krishna 		return true;
43*bdf79b12SSai Krishna 
44*bdf79b12SSai Krishna 	return false;
45*bdf79b12SSai Krishna }
46*bdf79b12SSai Krishna 
otx2_ptp_hw_adjtime(struct ptp_clock_info * ptp_info,s64 delta)47*bdf79b12SSai Krishna static int otx2_ptp_hw_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
48*bdf79b12SSai Krishna {
49*bdf79b12SSai Krishna 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
50*bdf79b12SSai Krishna 					    ptp_info);
51*bdf79b12SSai Krishna 	struct otx2_nic *pfvf = ptp->nic;
52*bdf79b12SSai Krishna 	struct ptp_req *req;
53*bdf79b12SSai Krishna 	int rc;
54*bdf79b12SSai Krishna 
55*bdf79b12SSai Krishna 	if (!ptp->nic)
56*bdf79b12SSai Krishna 		return -ENODEV;
57*bdf79b12SSai Krishna 
58*bdf79b12SSai Krishna 	mutex_lock(&pfvf->mbox.lock);
59*bdf79b12SSai Krishna 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
60*bdf79b12SSai Krishna 	if (!req) {
61*bdf79b12SSai Krishna 		mutex_unlock(&pfvf->mbox.lock);
62*bdf79b12SSai Krishna 		return -ENOMEM;
63*bdf79b12SSai Krishna 	}
64*bdf79b12SSai Krishna 	req->op = PTP_OP_ADJTIME;
65*bdf79b12SSai Krishna 	req->delta = delta;
66*bdf79b12SSai Krishna 	rc = otx2_sync_mbox_msg(&ptp->nic->mbox);
67*bdf79b12SSai Krishna 	mutex_unlock(&pfvf->mbox.lock);
68*bdf79b12SSai Krishna 
69*bdf79b12SSai Krishna 	return rc;
70*bdf79b12SSai Krishna }
71*bdf79b12SSai Krishna 
otx2_ptp_get_clock(struct otx2_ptp * ptp)722958d17aSHariprasad Kelam static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp)
732958d17aSHariprasad Kelam {
742958d17aSHariprasad Kelam 	struct ptp_req *req;
752958d17aSHariprasad Kelam 	struct ptp_rsp *rsp;
762958d17aSHariprasad Kelam 	int err;
772958d17aSHariprasad Kelam 
782958d17aSHariprasad Kelam 	if (!ptp->nic)
792958d17aSHariprasad Kelam 		return 0;
802958d17aSHariprasad Kelam 
812958d17aSHariprasad Kelam 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
822958d17aSHariprasad Kelam 	if (!req)
832958d17aSHariprasad Kelam 		return 0;
842958d17aSHariprasad Kelam 
852958d17aSHariprasad Kelam 	req->op = PTP_OP_GET_CLOCK;
862958d17aSHariprasad Kelam 
872958d17aSHariprasad Kelam 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
882958d17aSHariprasad Kelam 	if (err)
892958d17aSHariprasad Kelam 		return 0;
902958d17aSHariprasad Kelam 
912958d17aSHariprasad Kelam 	rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
922958d17aSHariprasad Kelam 						  &req->hdr);
932958d17aSHariprasad Kelam 	if (IS_ERR(rsp))
942958d17aSHariprasad Kelam 		return 0;
952958d17aSHariprasad Kelam 
962958d17aSHariprasad Kelam 	return rsp->clk;
972958d17aSHariprasad Kelam }
982958d17aSHariprasad Kelam 
otx2_ptp_hw_gettime(struct ptp_clock_info * ptp_info,struct timespec64 * ts)99*bdf79b12SSai Krishna static int otx2_ptp_hw_gettime(struct ptp_clock_info *ptp_info,
100*bdf79b12SSai Krishna 			       struct timespec64 *ts)
101*bdf79b12SSai Krishna {
102*bdf79b12SSai Krishna 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
103*bdf79b12SSai Krishna 					    ptp_info);
104*bdf79b12SSai Krishna 	u64 tstamp;
105*bdf79b12SSai Krishna 
106*bdf79b12SSai Krishna 	tstamp = otx2_ptp_get_clock(ptp);
107*bdf79b12SSai Krishna 
108*bdf79b12SSai Krishna 	*ts = ns_to_timespec64(tstamp);
109*bdf79b12SSai Krishna 	return 0;
110*bdf79b12SSai Krishna }
111*bdf79b12SSai Krishna 
otx2_ptp_hw_settime(struct ptp_clock_info * ptp_info,const struct timespec64 * ts)112*bdf79b12SSai Krishna static int otx2_ptp_hw_settime(struct ptp_clock_info *ptp_info,
113*bdf79b12SSai Krishna 			       const struct timespec64 *ts)
114*bdf79b12SSai Krishna {
115*bdf79b12SSai Krishna 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
116*bdf79b12SSai Krishna 					    ptp_info);
117*bdf79b12SSai Krishna 	struct otx2_nic *pfvf = ptp->nic;
118*bdf79b12SSai Krishna 	struct ptp_req *req;
119*bdf79b12SSai Krishna 	u64 nsec;
120*bdf79b12SSai Krishna 	int rc;
121*bdf79b12SSai Krishna 
122*bdf79b12SSai Krishna 	if (!ptp->nic)
123*bdf79b12SSai Krishna 		return -ENODEV;
124*bdf79b12SSai Krishna 
125*bdf79b12SSai Krishna 	nsec = timespec64_to_ns(ts);
126*bdf79b12SSai Krishna 
127*bdf79b12SSai Krishna 	mutex_lock(&pfvf->mbox.lock);
128*bdf79b12SSai Krishna 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
129*bdf79b12SSai Krishna 	if (!req) {
130*bdf79b12SSai Krishna 		mutex_unlock(&pfvf->mbox.lock);
131*bdf79b12SSai Krishna 		return -ENOMEM;
132*bdf79b12SSai Krishna 	}
133*bdf79b12SSai Krishna 
134*bdf79b12SSai Krishna 	req->op = PTP_OP_SET_CLOCK;
135*bdf79b12SSai Krishna 	req->clk = nsec;
136*bdf79b12SSai Krishna 	rc = otx2_sync_mbox_msg(&ptp->nic->mbox);
137*bdf79b12SSai Krishna 	mutex_unlock(&pfvf->mbox.lock);
138*bdf79b12SSai Krishna 
139*bdf79b12SSai Krishna 	return rc;
140*bdf79b12SSai Krishna }
141*bdf79b12SSai Krishna 
otx2_ptp_adjfine(struct ptp_clock_info * ptp_info,long scaled_ppm)142c9c12d33SAleksey Makarov static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
143c9c12d33SAleksey Makarov {
144c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
145c9c12d33SAleksey Makarov 					    ptp_info);
146c9c12d33SAleksey Makarov 	struct ptp_req *req;
147c9c12d33SAleksey Makarov 
148c9c12d33SAleksey Makarov 	if (!ptp->nic)
149c9c12d33SAleksey Makarov 		return -ENODEV;
150c9c12d33SAleksey Makarov 
151c9c12d33SAleksey Makarov 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
152c9c12d33SAleksey Makarov 	if (!req)
153c9c12d33SAleksey Makarov 		return -ENOMEM;
154c9c12d33SAleksey Makarov 
155c9c12d33SAleksey Makarov 	req->op = PTP_OP_ADJFINE;
156c9c12d33SAleksey Makarov 	req->scaled_ppm = scaled_ppm;
157c9c12d33SAleksey Makarov 
158b8d90937SZheng Yongjun 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
159c9c12d33SAleksey Makarov }
160c9c12d33SAleksey Makarov 
ptp_set_thresh(struct otx2_ptp * ptp,u64 thresh)16199bbc4aeSYi Guo static int ptp_set_thresh(struct otx2_ptp *ptp, u64 thresh)
16299bbc4aeSYi Guo {
16399bbc4aeSYi Guo 	struct ptp_req *req;
16499bbc4aeSYi Guo 
16599bbc4aeSYi Guo 	if (!ptp->nic)
16699bbc4aeSYi Guo 		return -ENODEV;
16799bbc4aeSYi Guo 
16899bbc4aeSYi Guo 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
16999bbc4aeSYi Guo 	if (!req)
17099bbc4aeSYi Guo 		return -ENOMEM;
17199bbc4aeSYi Guo 
17299bbc4aeSYi Guo 	req->op = PTP_OP_SET_THRESH;
17399bbc4aeSYi Guo 	req->thresh = thresh;
17499bbc4aeSYi Guo 
17599bbc4aeSYi Guo 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
17699bbc4aeSYi Guo }
17799bbc4aeSYi Guo 
ptp_extts_on(struct otx2_ptp * ptp,int on)1782ef4e45dSNaveen Mamindlapalli static int ptp_extts_on(struct otx2_ptp *ptp, int on)
1792ef4e45dSNaveen Mamindlapalli {
1802ef4e45dSNaveen Mamindlapalli 	struct ptp_req *req;
1812ef4e45dSNaveen Mamindlapalli 
1822ef4e45dSNaveen Mamindlapalli 	if (!ptp->nic)
1832ef4e45dSNaveen Mamindlapalli 		return -ENODEV;
1842ef4e45dSNaveen Mamindlapalli 
1852ef4e45dSNaveen Mamindlapalli 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
1862ef4e45dSNaveen Mamindlapalli 	if (!req)
1872ef4e45dSNaveen Mamindlapalli 		return -ENOMEM;
1882ef4e45dSNaveen Mamindlapalli 
1892ef4e45dSNaveen Mamindlapalli 	req->op = PTP_OP_EXTTS_ON;
1902ef4e45dSNaveen Mamindlapalli 	req->extts_on = on;
1912ef4e45dSNaveen Mamindlapalli 
1922ef4e45dSNaveen Mamindlapalli 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
1932ef4e45dSNaveen Mamindlapalli }
1942ef4e45dSNaveen Mamindlapalli 
ptp_cc_read(const struct cyclecounter * cc)195c9c12d33SAleksey Makarov static u64 ptp_cc_read(const struct cyclecounter *cc)
196c9c12d33SAleksey Makarov {
197c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter);
198c9c12d33SAleksey Makarov 
1992958d17aSHariprasad Kelam 	return otx2_ptp_get_clock(ptp);
200c9c12d33SAleksey Makarov }
201c9c12d33SAleksey Makarov 
ptp_tstmp_read(struct otx2_ptp * ptp)20299bbc4aeSYi Guo static u64 ptp_tstmp_read(struct otx2_ptp *ptp)
20399bbc4aeSYi Guo {
20499bbc4aeSYi Guo 	struct ptp_req *req;
20599bbc4aeSYi Guo 	struct ptp_rsp *rsp;
20699bbc4aeSYi Guo 	int err;
20799bbc4aeSYi Guo 
20899bbc4aeSYi Guo 	if (!ptp->nic)
20999bbc4aeSYi Guo 		return 0;
21099bbc4aeSYi Guo 
21199bbc4aeSYi Guo 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
21299bbc4aeSYi Guo 	if (!req)
21399bbc4aeSYi Guo 		return 0;
21499bbc4aeSYi Guo 
21599bbc4aeSYi Guo 	req->op = PTP_OP_GET_TSTMP;
21699bbc4aeSYi Guo 
21799bbc4aeSYi Guo 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
21899bbc4aeSYi Guo 	if (err)
21999bbc4aeSYi Guo 		return 0;
22099bbc4aeSYi Guo 
22199bbc4aeSYi Guo 	rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
22299bbc4aeSYi Guo 						  &req->hdr);
22399bbc4aeSYi Guo 	if (IS_ERR(rsp))
22499bbc4aeSYi Guo 		return 0;
22599bbc4aeSYi Guo 
22699bbc4aeSYi Guo 	return rsp->clk;
22799bbc4aeSYi Guo }
22899bbc4aeSYi Guo 
otx2_ptp_tc_adjtime(struct ptp_clock_info * ptp_info,s64 delta)229*bdf79b12SSai Krishna static int otx2_ptp_tc_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
230c9c12d33SAleksey Makarov {
231c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
232c9c12d33SAleksey Makarov 					    ptp_info);
233c9c12d33SAleksey Makarov 	struct otx2_nic *pfvf = ptp->nic;
234c9c12d33SAleksey Makarov 
235c9c12d33SAleksey Makarov 	mutex_lock(&pfvf->mbox.lock);
236c9c12d33SAleksey Makarov 	timecounter_adjtime(&ptp->time_counter, delta);
237c9c12d33SAleksey Makarov 	mutex_unlock(&pfvf->mbox.lock);
238c9c12d33SAleksey Makarov 
239c9c12d33SAleksey Makarov 	return 0;
240c9c12d33SAleksey Makarov }
241c9c12d33SAleksey Makarov 
otx2_ptp_tc_gettime(struct ptp_clock_info * ptp_info,struct timespec64 * ts)242*bdf79b12SSai Krishna static int otx2_ptp_tc_gettime(struct ptp_clock_info *ptp_info,
243c9c12d33SAleksey Makarov 			       struct timespec64 *ts)
244c9c12d33SAleksey Makarov {
245c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
246c9c12d33SAleksey Makarov 					    ptp_info);
2472958d17aSHariprasad Kelam 	u64 tstamp;
248c9c12d33SAleksey Makarov 
249*bdf79b12SSai Krishna 	mutex_lock(&ptp->nic->mbox.lock);
250*bdf79b12SSai Krishna 	tstamp = timecounter_read(&ptp->time_counter);
251*bdf79b12SSai Krishna 	mutex_unlock(&ptp->nic->mbox.lock);
2522958d17aSHariprasad Kelam 	*ts = ns_to_timespec64(tstamp);
253c9c12d33SAleksey Makarov 
254c9c12d33SAleksey Makarov 	return 0;
255c9c12d33SAleksey Makarov }
256c9c12d33SAleksey Makarov 
otx2_ptp_tc_settime(struct ptp_clock_info * ptp_info,const struct timespec64 * ts)257*bdf79b12SSai Krishna static int otx2_ptp_tc_settime(struct ptp_clock_info *ptp_info,
258c9c12d33SAleksey Makarov 			       const struct timespec64 *ts)
259c9c12d33SAleksey Makarov {
260c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
261c9c12d33SAleksey Makarov 					    ptp_info);
262c9c12d33SAleksey Makarov 	u64 nsec;
263c9c12d33SAleksey Makarov 
264c9c12d33SAleksey Makarov 	nsec = timespec64_to_ns(ts);
265c9c12d33SAleksey Makarov 
266*bdf79b12SSai Krishna 	mutex_lock(&ptp->nic->mbox.lock);
267c9c12d33SAleksey Makarov 	timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
268*bdf79b12SSai Krishna 	mutex_unlock(&ptp->nic->mbox.lock);
269c9c12d33SAleksey Makarov 
270c9c12d33SAleksey Makarov 	return 0;
271c9c12d33SAleksey Makarov }
272c9c12d33SAleksey Makarov 
otx2_ptp_verify_pin(struct ptp_clock_info * ptp,unsigned int pin,enum ptp_pin_function func,unsigned int chan)27399bbc4aeSYi Guo static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
27499bbc4aeSYi Guo 			       enum ptp_pin_function func, unsigned int chan)
27599bbc4aeSYi Guo {
27699bbc4aeSYi Guo 	switch (func) {
27799bbc4aeSYi Guo 	case PTP_PF_NONE:
27899bbc4aeSYi Guo 	case PTP_PF_EXTTS:
27999bbc4aeSYi Guo 		break;
28099bbc4aeSYi Guo 	case PTP_PF_PEROUT:
28199bbc4aeSYi Guo 	case PTP_PF_PHYSYNC:
28299bbc4aeSYi Guo 		return -1;
28399bbc4aeSYi Guo 	}
28499bbc4aeSYi Guo 	return 0;
28599bbc4aeSYi Guo }
28699bbc4aeSYi Guo 
otx2_ptp_hw_tstamp2time(const struct timecounter * time_counter,u64 tstamp)287*bdf79b12SSai Krishna static u64 otx2_ptp_hw_tstamp2time(const struct timecounter *time_counter, u64 tstamp)
288*bdf79b12SSai Krishna {
289*bdf79b12SSai Krishna 	/* On HW which supports atomic updates, timecounter is not initialized */
290*bdf79b12SSai Krishna 	return tstamp;
291*bdf79b12SSai Krishna }
292*bdf79b12SSai Krishna 
otx2_ptp_extts_check(struct work_struct * work)29399bbc4aeSYi Guo static void otx2_ptp_extts_check(struct work_struct *work)
29499bbc4aeSYi Guo {
29599bbc4aeSYi Guo 	struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
29699bbc4aeSYi Guo 					    extts_work.work);
29799bbc4aeSYi Guo 	struct ptp_clock_event event;
29899bbc4aeSYi Guo 	u64 tstmp, new_thresh;
29999bbc4aeSYi Guo 
30099bbc4aeSYi Guo 	mutex_lock(&ptp->nic->mbox.lock);
30199bbc4aeSYi Guo 	tstmp = ptp_tstmp_read(ptp);
30299bbc4aeSYi Guo 	mutex_unlock(&ptp->nic->mbox.lock);
30399bbc4aeSYi Guo 
30499bbc4aeSYi Guo 	if (tstmp != ptp->last_extts) {
30599bbc4aeSYi Guo 		event.type = PTP_CLOCK_EXTTS;
30699bbc4aeSYi Guo 		event.index = 0;
307*bdf79b12SSai Krishna 		event.timestamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstmp);
30899bbc4aeSYi Guo 		ptp_clock_event(ptp->ptp_clock, &event);
30999bbc4aeSYi Guo 		new_thresh = tstmp % 500000000;
31099bbc4aeSYi Guo 		if (ptp->thresh != new_thresh) {
31199bbc4aeSYi Guo 			mutex_lock(&ptp->nic->mbox.lock);
31299bbc4aeSYi Guo 			ptp_set_thresh(ptp, new_thresh);
31399bbc4aeSYi Guo 			mutex_unlock(&ptp->nic->mbox.lock);
31499bbc4aeSYi Guo 			ptp->thresh = new_thresh;
31599bbc4aeSYi Guo 		}
3162ef4e45dSNaveen Mamindlapalli 		ptp->last_extts = tstmp;
31799bbc4aeSYi Guo 	}
31899bbc4aeSYi Guo 	schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
31999bbc4aeSYi Guo }
32099bbc4aeSYi Guo 
otx2_sync_tstamp(struct work_struct * work)3212958d17aSHariprasad Kelam static void otx2_sync_tstamp(struct work_struct *work)
3222958d17aSHariprasad Kelam {
3232958d17aSHariprasad Kelam 	struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
3242958d17aSHariprasad Kelam 					    synctstamp_work.work);
3252958d17aSHariprasad Kelam 	struct otx2_nic *pfvf = ptp->nic;
3262958d17aSHariprasad Kelam 	u64 tstamp;
3272958d17aSHariprasad Kelam 
3282958d17aSHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
3292958d17aSHariprasad Kelam 	tstamp = otx2_ptp_get_clock(ptp);
3302958d17aSHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
3312958d17aSHariprasad Kelam 
332*bdf79b12SSai Krishna 	ptp->tstamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstamp);
3332958d17aSHariprasad Kelam 	ptp->base_ns = tstamp % NSEC_PER_SEC;
3342958d17aSHariprasad Kelam 
3352958d17aSHariprasad Kelam 	schedule_delayed_work(&ptp->synctstamp_work, msecs_to_jiffies(250));
3362958d17aSHariprasad Kelam }
3372958d17aSHariprasad Kelam 
otx2_ptp_enable(struct ptp_clock_info * ptp_info,struct ptp_clock_request * rq,int on)338c9c12d33SAleksey Makarov static int otx2_ptp_enable(struct ptp_clock_info *ptp_info,
339c9c12d33SAleksey Makarov 			   struct ptp_clock_request *rq, int on)
340c9c12d33SAleksey Makarov {
34199bbc4aeSYi Guo 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
34299bbc4aeSYi Guo 					    ptp_info);
34375f81afbSColin Ian King 	int pin;
34499bbc4aeSYi Guo 
34599bbc4aeSYi Guo 	if (!ptp->nic)
34699bbc4aeSYi Guo 		return -ENODEV;
34799bbc4aeSYi Guo 
34899bbc4aeSYi Guo 	switch (rq->type) {
34999bbc4aeSYi Guo 	case PTP_CLK_REQ_EXTTS:
35099bbc4aeSYi Guo 		pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS,
35199bbc4aeSYi Guo 				   rq->extts.index);
35299bbc4aeSYi Guo 		if (pin < 0)
35399bbc4aeSYi Guo 			return -EBUSY;
3542ef4e45dSNaveen Mamindlapalli 		if (on) {
3552ef4e45dSNaveen Mamindlapalli 			ptp_extts_on(ptp, on);
35699bbc4aeSYi Guo 			schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
3572ef4e45dSNaveen Mamindlapalli 		} else {
3582ef4e45dSNaveen Mamindlapalli 			ptp_extts_on(ptp, on);
35999bbc4aeSYi Guo 			cancel_delayed_work_sync(&ptp->extts_work);
3602ef4e45dSNaveen Mamindlapalli 		}
36199bbc4aeSYi Guo 		return 0;
36299bbc4aeSYi Guo 	default:
36399bbc4aeSYi Guo 		break;
36499bbc4aeSYi Guo 	}
365c9c12d33SAleksey Makarov 	return -EOPNOTSUPP;
366c9c12d33SAleksey Makarov }
367c9c12d33SAleksey Makarov 
otx2_ptp_init(struct otx2_nic * pfvf)368c9c12d33SAleksey Makarov int otx2_ptp_init(struct otx2_nic *pfvf)
369c9c12d33SAleksey Makarov {
370c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp_ptr;
371c9c12d33SAleksey Makarov 	struct cyclecounter *cc;
372c9c12d33SAleksey Makarov 	struct ptp_req *req;
373c9c12d33SAleksey Makarov 	int err;
374c9c12d33SAleksey Makarov 
37543510ef4SNaveen Mamindlapalli 	if (is_otx2_lbkvf(pfvf->pdev)) {
37643510ef4SNaveen Mamindlapalli 		pfvf->ptp = NULL;
37743510ef4SNaveen Mamindlapalli 		return 0;
37843510ef4SNaveen Mamindlapalli 	}
37943510ef4SNaveen Mamindlapalli 
380c9c12d33SAleksey Makarov 	mutex_lock(&pfvf->mbox.lock);
381c9c12d33SAleksey Makarov 	/* check if PTP block is available */
382c9c12d33SAleksey Makarov 	req = otx2_mbox_alloc_msg_ptp_op(&pfvf->mbox);
383c9c12d33SAleksey Makarov 	if (!req) {
384c9c12d33SAleksey Makarov 		mutex_unlock(&pfvf->mbox.lock);
385c9c12d33SAleksey Makarov 		return -ENOMEM;
386c9c12d33SAleksey Makarov 	}
387c9c12d33SAleksey Makarov 
388c9c12d33SAleksey Makarov 	req->op = PTP_OP_GET_CLOCK;
389c9c12d33SAleksey Makarov 
390c9c12d33SAleksey Makarov 	err = otx2_sync_mbox_msg(&pfvf->mbox);
391c9c12d33SAleksey Makarov 	if (err) {
392c9c12d33SAleksey Makarov 		mutex_unlock(&pfvf->mbox.lock);
393c9c12d33SAleksey Makarov 		return err;
394c9c12d33SAleksey Makarov 	}
395c9c12d33SAleksey Makarov 	mutex_unlock(&pfvf->mbox.lock);
396c9c12d33SAleksey Makarov 
397c9c12d33SAleksey Makarov 	ptp_ptr = kzalloc(sizeof(*ptp_ptr), GFP_KERNEL);
398c9c12d33SAleksey Makarov 	if (!ptp_ptr) {
399c9c12d33SAleksey Makarov 		err = -ENOMEM;
400c9c12d33SAleksey Makarov 		goto error;
401c9c12d33SAleksey Makarov 	}
402c9c12d33SAleksey Makarov 
403c9c12d33SAleksey Makarov 	ptp_ptr->nic = pfvf;
404c9c12d33SAleksey Makarov 
40599bbc4aeSYi Guo 	snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP");
40699bbc4aeSYi Guo 	ptp_ptr->extts_config.index = 0;
40799bbc4aeSYi Guo 	ptp_ptr->extts_config.func = PTP_PF_NONE;
40899bbc4aeSYi Guo 
409c9c12d33SAleksey Makarov 	ptp_ptr->ptp_info = (struct ptp_clock_info) {
410c9c12d33SAleksey Makarov 		.owner          = THIS_MODULE,
411c9c12d33SAleksey Makarov 		.name           = "OcteonTX2 PTP",
412c9c12d33SAleksey Makarov 		.max_adj        = 1000000000ull,
41399bbc4aeSYi Guo 		.n_ext_ts       = 1,
41499bbc4aeSYi Guo 		.n_pins         = 1,
415c9c12d33SAleksey Makarov 		.pps            = 0,
41699bbc4aeSYi Guo 		.pin_config     = &ptp_ptr->extts_config,
417c9c12d33SAleksey Makarov 		.adjfine        = otx2_ptp_adjfine,
418c9c12d33SAleksey Makarov 		.enable         = otx2_ptp_enable,
41999bbc4aeSYi Guo 		.verify         = otx2_ptp_verify_pin,
420c9c12d33SAleksey Makarov 	};
421c9c12d33SAleksey Makarov 
422*bdf79b12SSai Krishna 	/* Check whether hardware supports atomic updates to timestamp */
423*bdf79b12SSai Krishna 	if (is_tstmp_atomic_update_supported(ptp_ptr)) {
424*bdf79b12SSai Krishna 		ptp_ptr->ptp_info.adjtime = otx2_ptp_hw_adjtime;
425*bdf79b12SSai Krishna 		ptp_ptr->ptp_info.gettime64 = otx2_ptp_hw_gettime;
426*bdf79b12SSai Krishna 		ptp_ptr->ptp_info.settime64 = otx2_ptp_hw_settime;
427*bdf79b12SSai Krishna 
428*bdf79b12SSai Krishna 		ptp_ptr->ptp_tstamp2nsec = otx2_ptp_hw_tstamp2time;
429*bdf79b12SSai Krishna 	} else {
430*bdf79b12SSai Krishna 		ptp_ptr->ptp_info.adjtime = otx2_ptp_tc_adjtime;
431*bdf79b12SSai Krishna 		ptp_ptr->ptp_info.gettime64 = otx2_ptp_tc_gettime;
432*bdf79b12SSai Krishna 		ptp_ptr->ptp_info.settime64 = otx2_ptp_tc_settime;
433*bdf79b12SSai Krishna 
434*bdf79b12SSai Krishna 		cc = &ptp_ptr->cycle_counter;
435*bdf79b12SSai Krishna 		cc->read = ptp_cc_read;
436*bdf79b12SSai Krishna 		cc->mask = CYCLECOUNTER_MASK(64);
437*bdf79b12SSai Krishna 		cc->mult = 1;
438*bdf79b12SSai Krishna 		cc->shift = 0;
439*bdf79b12SSai Krishna 		ptp_ptr->ptp_tstamp2nsec = timecounter_cyc2time;
440*bdf79b12SSai Krishna 
441*bdf79b12SSai Krishna 		timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
442*bdf79b12SSai Krishna 				 ktime_to_ns(ktime_get_real()));
443*bdf79b12SSai Krishna 	}
444*bdf79b12SSai Krishna 
44599bbc4aeSYi Guo 	INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check);
44699bbc4aeSYi Guo 
447c9c12d33SAleksey Makarov 	ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev);
448c9c12d33SAleksey Makarov 	if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) {
449c9c12d33SAleksey Makarov 		err = ptp_ptr->ptp_clock ?
450c9c12d33SAleksey Makarov 		      PTR_ERR(ptp_ptr->ptp_clock) : -ENODEV;
451c9c12d33SAleksey Makarov 		kfree(ptp_ptr);
452c9c12d33SAleksey Makarov 		goto error;
453c9c12d33SAleksey Makarov 	}
454c9c12d33SAleksey Makarov 
45574c1b233SNaveen Mamindlapalli 	if (is_dev_otx2(pfvf->pdev)) {
45674c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_rx_ptp_tstmp = &otx2_ptp_convert_rx_timestamp;
45774c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_tx_ptp_tstmp = &otx2_ptp_convert_tx_timestamp;
45874c1b233SNaveen Mamindlapalli 	} else {
45974c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_rx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
46074c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_tx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
46174c1b233SNaveen Mamindlapalli 	}
46274c1b233SNaveen Mamindlapalli 
4632958d17aSHariprasad Kelam 	INIT_DELAYED_WORK(&ptp_ptr->synctstamp_work, otx2_sync_tstamp);
4642958d17aSHariprasad Kelam 
465c9c12d33SAleksey Makarov 	pfvf->ptp = ptp_ptr;
466c9c12d33SAleksey Makarov 
467c9c12d33SAleksey Makarov error:
468c9c12d33SAleksey Makarov 	return err;
469c9c12d33SAleksey Makarov }
4700e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_init);
471c9c12d33SAleksey Makarov 
otx2_ptp_destroy(struct otx2_nic * pfvf)472c9c12d33SAleksey Makarov void otx2_ptp_destroy(struct otx2_nic *pfvf)
473c9c12d33SAleksey Makarov {
474c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = pfvf->ptp;
475c9c12d33SAleksey Makarov 
476c9c12d33SAleksey Makarov 	if (!ptp)
477c9c12d33SAleksey Makarov 		return;
478c9c12d33SAleksey Makarov 
4792958d17aSHariprasad Kelam 	cancel_delayed_work(&pfvf->ptp->synctstamp_work);
4802958d17aSHariprasad Kelam 
481c9c12d33SAleksey Makarov 	ptp_clock_unregister(ptp->ptp_clock);
482c9c12d33SAleksey Makarov 	kfree(ptp);
483c9c12d33SAleksey Makarov 	pfvf->ptp = NULL;
484c9c12d33SAleksey Makarov }
4850e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_destroy);
486c9c12d33SAleksey Makarov 
otx2_ptp_clock_index(struct otx2_nic * pfvf)487c9c12d33SAleksey Makarov int otx2_ptp_clock_index(struct otx2_nic *pfvf)
488c9c12d33SAleksey Makarov {
489c9c12d33SAleksey Makarov 	if (!pfvf->ptp)
490c9c12d33SAleksey Makarov 		return -ENODEV;
491c9c12d33SAleksey Makarov 
492c9c12d33SAleksey Makarov 	return ptp_clock_index(pfvf->ptp->ptp_clock);
493c9c12d33SAleksey Makarov }
4940e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_clock_index);
495c9c12d33SAleksey Makarov 
otx2_ptp_tstamp2time(struct otx2_nic * pfvf,u64 tstamp,u64 * tsns)496c9c12d33SAleksey Makarov int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns)
497c9c12d33SAleksey Makarov {
498c9c12d33SAleksey Makarov 	if (!pfvf->ptp)
499c9c12d33SAleksey Makarov 		return -ENODEV;
500c9c12d33SAleksey Makarov 
501*bdf79b12SSai Krishna 	*tsns = pfvf->ptp->ptp_tstamp2nsec(&pfvf->ptp->time_counter, tstamp);
502c9c12d33SAleksey Makarov 
503c9c12d33SAleksey Makarov 	return 0;
504c9c12d33SAleksey Makarov }
5050e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_tstamp2time);
5060e9e7598SArnd Bergmann 
5070e9e7598SArnd Bergmann MODULE_AUTHOR("Sunil Goutham <sgoutham@marvell.com>");
5080e9e7598SArnd Bergmann MODULE_DESCRIPTION("Marvell RVU NIC PTP Driver");
5090e9e7598SArnd Bergmann MODULE_LICENSE("GPL v2");
510