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 
132958d17aSHariprasad Kelam static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp)
142958d17aSHariprasad Kelam {
152958d17aSHariprasad Kelam 	struct ptp_req *req;
162958d17aSHariprasad Kelam 	struct ptp_rsp *rsp;
172958d17aSHariprasad Kelam 	int err;
182958d17aSHariprasad Kelam 
192958d17aSHariprasad Kelam 	if (!ptp->nic)
202958d17aSHariprasad Kelam 		return 0;
212958d17aSHariprasad Kelam 
222958d17aSHariprasad Kelam 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
232958d17aSHariprasad Kelam 	if (!req)
242958d17aSHariprasad Kelam 		return 0;
252958d17aSHariprasad Kelam 
262958d17aSHariprasad Kelam 	req->op = PTP_OP_GET_CLOCK;
272958d17aSHariprasad Kelam 
282958d17aSHariprasad Kelam 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
292958d17aSHariprasad Kelam 	if (err)
302958d17aSHariprasad Kelam 		return 0;
312958d17aSHariprasad Kelam 
322958d17aSHariprasad Kelam 	rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
332958d17aSHariprasad Kelam 						  &req->hdr);
342958d17aSHariprasad Kelam 	if (IS_ERR(rsp))
352958d17aSHariprasad Kelam 		return 0;
362958d17aSHariprasad Kelam 
372958d17aSHariprasad Kelam 	return rsp->clk;
382958d17aSHariprasad Kelam }
392958d17aSHariprasad Kelam 
40c9c12d33SAleksey Makarov static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
41c9c12d33SAleksey Makarov {
42c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
43c9c12d33SAleksey Makarov 					    ptp_info);
44c9c12d33SAleksey Makarov 	struct ptp_req *req;
45c9c12d33SAleksey Makarov 
46c9c12d33SAleksey Makarov 	if (!ptp->nic)
47c9c12d33SAleksey Makarov 		return -ENODEV;
48c9c12d33SAleksey Makarov 
49c9c12d33SAleksey Makarov 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
50c9c12d33SAleksey Makarov 	if (!req)
51c9c12d33SAleksey Makarov 		return -ENOMEM;
52c9c12d33SAleksey Makarov 
53c9c12d33SAleksey Makarov 	req->op = PTP_OP_ADJFINE;
54c9c12d33SAleksey Makarov 	req->scaled_ppm = scaled_ppm;
55c9c12d33SAleksey Makarov 
56b8d90937SZheng Yongjun 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
57c9c12d33SAleksey Makarov }
58c9c12d33SAleksey Makarov 
5999bbc4aeSYi Guo static int ptp_set_thresh(struct otx2_ptp *ptp, u64 thresh)
6099bbc4aeSYi Guo {
6199bbc4aeSYi Guo 	struct ptp_req *req;
6299bbc4aeSYi Guo 
6399bbc4aeSYi Guo 	if (!ptp->nic)
6499bbc4aeSYi Guo 		return -ENODEV;
6599bbc4aeSYi Guo 
6699bbc4aeSYi Guo 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
6799bbc4aeSYi Guo 	if (!req)
6899bbc4aeSYi Guo 		return -ENOMEM;
6999bbc4aeSYi Guo 
7099bbc4aeSYi Guo 	req->op = PTP_OP_SET_THRESH;
7199bbc4aeSYi Guo 	req->thresh = thresh;
7299bbc4aeSYi Guo 
7399bbc4aeSYi Guo 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
7499bbc4aeSYi Guo }
7599bbc4aeSYi Guo 
76*2ef4e45dSNaveen Mamindlapalli static int ptp_extts_on(struct otx2_ptp *ptp, int on)
77*2ef4e45dSNaveen Mamindlapalli {
78*2ef4e45dSNaveen Mamindlapalli 	struct ptp_req *req;
79*2ef4e45dSNaveen Mamindlapalli 
80*2ef4e45dSNaveen Mamindlapalli 	if (!ptp->nic)
81*2ef4e45dSNaveen Mamindlapalli 		return -ENODEV;
82*2ef4e45dSNaveen Mamindlapalli 
83*2ef4e45dSNaveen Mamindlapalli 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
84*2ef4e45dSNaveen Mamindlapalli 	if (!req)
85*2ef4e45dSNaveen Mamindlapalli 		return -ENOMEM;
86*2ef4e45dSNaveen Mamindlapalli 
87*2ef4e45dSNaveen Mamindlapalli 	req->op = PTP_OP_EXTTS_ON;
88*2ef4e45dSNaveen Mamindlapalli 	req->extts_on = on;
89*2ef4e45dSNaveen Mamindlapalli 
90*2ef4e45dSNaveen Mamindlapalli 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
91*2ef4e45dSNaveen Mamindlapalli }
92*2ef4e45dSNaveen Mamindlapalli 
93c9c12d33SAleksey Makarov static u64 ptp_cc_read(const struct cyclecounter *cc)
94c9c12d33SAleksey Makarov {
95c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter);
96c9c12d33SAleksey Makarov 
972958d17aSHariprasad Kelam 	return otx2_ptp_get_clock(ptp);
98c9c12d33SAleksey Makarov }
99c9c12d33SAleksey Makarov 
10099bbc4aeSYi Guo static u64 ptp_tstmp_read(struct otx2_ptp *ptp)
10199bbc4aeSYi Guo {
10299bbc4aeSYi Guo 	struct ptp_req *req;
10399bbc4aeSYi Guo 	struct ptp_rsp *rsp;
10499bbc4aeSYi Guo 	int err;
10599bbc4aeSYi Guo 
10699bbc4aeSYi Guo 	if (!ptp->nic)
10799bbc4aeSYi Guo 		return 0;
10899bbc4aeSYi Guo 
10999bbc4aeSYi Guo 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
11099bbc4aeSYi Guo 	if (!req)
11199bbc4aeSYi Guo 		return 0;
11299bbc4aeSYi Guo 
11399bbc4aeSYi Guo 	req->op = PTP_OP_GET_TSTMP;
11499bbc4aeSYi Guo 
11599bbc4aeSYi Guo 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
11699bbc4aeSYi Guo 	if (err)
11799bbc4aeSYi Guo 		return 0;
11899bbc4aeSYi Guo 
11999bbc4aeSYi Guo 	rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
12099bbc4aeSYi Guo 						  &req->hdr);
12199bbc4aeSYi Guo 	if (IS_ERR(rsp))
12299bbc4aeSYi Guo 		return 0;
12399bbc4aeSYi Guo 
12499bbc4aeSYi Guo 	return rsp->clk;
12599bbc4aeSYi Guo }
12699bbc4aeSYi Guo 
1272958d17aSHariprasad Kelam static void otx2_get_ptpclock(struct otx2_ptp *ptp, u64 *tstamp)
1282958d17aSHariprasad Kelam {
1292958d17aSHariprasad Kelam 	struct otx2_nic *pfvf = ptp->nic;
1302958d17aSHariprasad Kelam 
1312958d17aSHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
1322958d17aSHariprasad Kelam 	*tstamp = timecounter_read(&ptp->time_counter);
1332958d17aSHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
1342958d17aSHariprasad Kelam }
1352958d17aSHariprasad Kelam 
136c9c12d33SAleksey Makarov static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
137c9c12d33SAleksey Makarov {
138c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
139c9c12d33SAleksey Makarov 					    ptp_info);
140c9c12d33SAleksey Makarov 	struct otx2_nic *pfvf = ptp->nic;
141c9c12d33SAleksey Makarov 
142c9c12d33SAleksey Makarov 	mutex_lock(&pfvf->mbox.lock);
143c9c12d33SAleksey Makarov 	timecounter_adjtime(&ptp->time_counter, delta);
144c9c12d33SAleksey Makarov 	mutex_unlock(&pfvf->mbox.lock);
145c9c12d33SAleksey Makarov 
146c9c12d33SAleksey Makarov 	return 0;
147c9c12d33SAleksey Makarov }
148c9c12d33SAleksey Makarov 
149c9c12d33SAleksey Makarov static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info,
150c9c12d33SAleksey Makarov 			    struct timespec64 *ts)
151c9c12d33SAleksey Makarov {
152c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
153c9c12d33SAleksey Makarov 					    ptp_info);
1542958d17aSHariprasad Kelam 	u64 tstamp;
155c9c12d33SAleksey Makarov 
1562958d17aSHariprasad Kelam 	otx2_get_ptpclock(ptp, &tstamp);
1572958d17aSHariprasad Kelam 	*ts = ns_to_timespec64(tstamp);
158c9c12d33SAleksey Makarov 
159c9c12d33SAleksey Makarov 	return 0;
160c9c12d33SAleksey Makarov }
161c9c12d33SAleksey Makarov 
162c9c12d33SAleksey Makarov static int otx2_ptp_settime(struct ptp_clock_info *ptp_info,
163c9c12d33SAleksey Makarov 			    const struct timespec64 *ts)
164c9c12d33SAleksey Makarov {
165c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
166c9c12d33SAleksey Makarov 					    ptp_info);
167c9c12d33SAleksey Makarov 	struct otx2_nic *pfvf = ptp->nic;
168c9c12d33SAleksey Makarov 	u64 nsec;
169c9c12d33SAleksey Makarov 
170c9c12d33SAleksey Makarov 	nsec = timespec64_to_ns(ts);
171c9c12d33SAleksey Makarov 
172c9c12d33SAleksey Makarov 	mutex_lock(&pfvf->mbox.lock);
173c9c12d33SAleksey Makarov 	timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
174c9c12d33SAleksey Makarov 	mutex_unlock(&pfvf->mbox.lock);
175c9c12d33SAleksey Makarov 
176c9c12d33SAleksey Makarov 	return 0;
177c9c12d33SAleksey Makarov }
178c9c12d33SAleksey Makarov 
17999bbc4aeSYi Guo static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
18099bbc4aeSYi Guo 			       enum ptp_pin_function func, unsigned int chan)
18199bbc4aeSYi Guo {
18299bbc4aeSYi Guo 	switch (func) {
18399bbc4aeSYi Guo 	case PTP_PF_NONE:
18499bbc4aeSYi Guo 	case PTP_PF_EXTTS:
18599bbc4aeSYi Guo 		break;
18699bbc4aeSYi Guo 	case PTP_PF_PEROUT:
18799bbc4aeSYi Guo 	case PTP_PF_PHYSYNC:
18899bbc4aeSYi Guo 		return -1;
18999bbc4aeSYi Guo 	}
19099bbc4aeSYi Guo 	return 0;
19199bbc4aeSYi Guo }
19299bbc4aeSYi Guo 
19399bbc4aeSYi Guo static void otx2_ptp_extts_check(struct work_struct *work)
19499bbc4aeSYi Guo {
19599bbc4aeSYi Guo 	struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
19699bbc4aeSYi Guo 					    extts_work.work);
19799bbc4aeSYi Guo 	struct ptp_clock_event event;
19899bbc4aeSYi Guo 	u64 tstmp, new_thresh;
19999bbc4aeSYi Guo 
20099bbc4aeSYi Guo 	mutex_lock(&ptp->nic->mbox.lock);
20199bbc4aeSYi Guo 	tstmp = ptp_tstmp_read(ptp);
20299bbc4aeSYi Guo 	mutex_unlock(&ptp->nic->mbox.lock);
20399bbc4aeSYi Guo 
20499bbc4aeSYi Guo 	if (tstmp != ptp->last_extts) {
20599bbc4aeSYi Guo 		event.type = PTP_CLOCK_EXTTS;
20699bbc4aeSYi Guo 		event.index = 0;
20799bbc4aeSYi Guo 		event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp);
20899bbc4aeSYi Guo 		ptp_clock_event(ptp->ptp_clock, &event);
20999bbc4aeSYi Guo 		new_thresh = tstmp % 500000000;
21099bbc4aeSYi Guo 		if (ptp->thresh != new_thresh) {
21199bbc4aeSYi Guo 			mutex_lock(&ptp->nic->mbox.lock);
21299bbc4aeSYi Guo 			ptp_set_thresh(ptp, new_thresh);
21399bbc4aeSYi Guo 			mutex_unlock(&ptp->nic->mbox.lock);
21499bbc4aeSYi Guo 			ptp->thresh = new_thresh;
21599bbc4aeSYi Guo 		}
216*2ef4e45dSNaveen Mamindlapalli 		ptp->last_extts = tstmp;
21799bbc4aeSYi Guo 	}
21899bbc4aeSYi Guo 	schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
21999bbc4aeSYi Guo }
22099bbc4aeSYi Guo 
2212958d17aSHariprasad Kelam static void otx2_sync_tstamp(struct work_struct *work)
2222958d17aSHariprasad Kelam {
2232958d17aSHariprasad Kelam 	struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
2242958d17aSHariprasad Kelam 					    synctstamp_work.work);
2252958d17aSHariprasad Kelam 	struct otx2_nic *pfvf = ptp->nic;
2262958d17aSHariprasad Kelam 	u64 tstamp;
2272958d17aSHariprasad Kelam 
2282958d17aSHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
2292958d17aSHariprasad Kelam 	tstamp = otx2_ptp_get_clock(ptp);
2302958d17aSHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
2312958d17aSHariprasad Kelam 
2322958d17aSHariprasad Kelam 	ptp->tstamp = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
2332958d17aSHariprasad Kelam 	ptp->base_ns = tstamp % NSEC_PER_SEC;
2342958d17aSHariprasad Kelam 
2352958d17aSHariprasad Kelam 	schedule_delayed_work(&ptp->synctstamp_work, msecs_to_jiffies(250));
2362958d17aSHariprasad Kelam }
2372958d17aSHariprasad Kelam 
238c9c12d33SAleksey Makarov static int otx2_ptp_enable(struct ptp_clock_info *ptp_info,
239c9c12d33SAleksey Makarov 			   struct ptp_clock_request *rq, int on)
240c9c12d33SAleksey Makarov {
24199bbc4aeSYi Guo 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
24299bbc4aeSYi Guo 					    ptp_info);
24375f81afbSColin Ian King 	int pin;
24499bbc4aeSYi Guo 
24599bbc4aeSYi Guo 	if (!ptp->nic)
24699bbc4aeSYi Guo 		return -ENODEV;
24799bbc4aeSYi Guo 
24899bbc4aeSYi Guo 	switch (rq->type) {
24999bbc4aeSYi Guo 	case PTP_CLK_REQ_EXTTS:
25099bbc4aeSYi Guo 		pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS,
25199bbc4aeSYi Guo 				   rq->extts.index);
25299bbc4aeSYi Guo 		if (pin < 0)
25399bbc4aeSYi Guo 			return -EBUSY;
254*2ef4e45dSNaveen Mamindlapalli 		if (on) {
255*2ef4e45dSNaveen Mamindlapalli 			ptp_extts_on(ptp, on);
25699bbc4aeSYi Guo 			schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
257*2ef4e45dSNaveen Mamindlapalli 		} else {
258*2ef4e45dSNaveen Mamindlapalli 			ptp_extts_on(ptp, on);
25999bbc4aeSYi Guo 			cancel_delayed_work_sync(&ptp->extts_work);
260*2ef4e45dSNaveen Mamindlapalli 		}
26199bbc4aeSYi Guo 		return 0;
26299bbc4aeSYi Guo 	default:
26399bbc4aeSYi Guo 		break;
26499bbc4aeSYi Guo 	}
265c9c12d33SAleksey Makarov 	return -EOPNOTSUPP;
266c9c12d33SAleksey Makarov }
267c9c12d33SAleksey Makarov 
268c9c12d33SAleksey Makarov int otx2_ptp_init(struct otx2_nic *pfvf)
269c9c12d33SAleksey Makarov {
270c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp_ptr;
271c9c12d33SAleksey Makarov 	struct cyclecounter *cc;
272c9c12d33SAleksey Makarov 	struct ptp_req *req;
273c9c12d33SAleksey Makarov 	int err;
274c9c12d33SAleksey Makarov 
27543510ef4SNaveen Mamindlapalli 	if (is_otx2_lbkvf(pfvf->pdev)) {
27643510ef4SNaveen Mamindlapalli 		pfvf->ptp = NULL;
27743510ef4SNaveen Mamindlapalli 		return 0;
27843510ef4SNaveen Mamindlapalli 	}
27943510ef4SNaveen Mamindlapalli 
280c9c12d33SAleksey Makarov 	mutex_lock(&pfvf->mbox.lock);
281c9c12d33SAleksey Makarov 	/* check if PTP block is available */
282c9c12d33SAleksey Makarov 	req = otx2_mbox_alloc_msg_ptp_op(&pfvf->mbox);
283c9c12d33SAleksey Makarov 	if (!req) {
284c9c12d33SAleksey Makarov 		mutex_unlock(&pfvf->mbox.lock);
285c9c12d33SAleksey Makarov 		return -ENOMEM;
286c9c12d33SAleksey Makarov 	}
287c9c12d33SAleksey Makarov 
288c9c12d33SAleksey Makarov 	req->op = PTP_OP_GET_CLOCK;
289c9c12d33SAleksey Makarov 
290c9c12d33SAleksey Makarov 	err = otx2_sync_mbox_msg(&pfvf->mbox);
291c9c12d33SAleksey Makarov 	if (err) {
292c9c12d33SAleksey Makarov 		mutex_unlock(&pfvf->mbox.lock);
293c9c12d33SAleksey Makarov 		return err;
294c9c12d33SAleksey Makarov 	}
295c9c12d33SAleksey Makarov 	mutex_unlock(&pfvf->mbox.lock);
296c9c12d33SAleksey Makarov 
297c9c12d33SAleksey Makarov 	ptp_ptr = kzalloc(sizeof(*ptp_ptr), GFP_KERNEL);
298c9c12d33SAleksey Makarov 	if (!ptp_ptr) {
299c9c12d33SAleksey Makarov 		err = -ENOMEM;
300c9c12d33SAleksey Makarov 		goto error;
301c9c12d33SAleksey Makarov 	}
302c9c12d33SAleksey Makarov 
303c9c12d33SAleksey Makarov 	ptp_ptr->nic = pfvf;
304c9c12d33SAleksey Makarov 
305c9c12d33SAleksey Makarov 	cc = &ptp_ptr->cycle_counter;
306c9c12d33SAleksey Makarov 	cc->read = ptp_cc_read;
307c9c12d33SAleksey Makarov 	cc->mask = CYCLECOUNTER_MASK(64);
308c9c12d33SAleksey Makarov 	cc->mult = 1;
309c9c12d33SAleksey Makarov 	cc->shift = 0;
310c9c12d33SAleksey Makarov 
311c9c12d33SAleksey Makarov 	timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
312c9c12d33SAleksey Makarov 			 ktime_to_ns(ktime_get_real()));
313c9c12d33SAleksey Makarov 
31499bbc4aeSYi Guo 	snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP");
31599bbc4aeSYi Guo 	ptp_ptr->extts_config.index = 0;
31699bbc4aeSYi Guo 	ptp_ptr->extts_config.func = PTP_PF_NONE;
31799bbc4aeSYi Guo 
318c9c12d33SAleksey Makarov 	ptp_ptr->ptp_info = (struct ptp_clock_info) {
319c9c12d33SAleksey Makarov 		.owner          = THIS_MODULE,
320c9c12d33SAleksey Makarov 		.name           = "OcteonTX2 PTP",
321c9c12d33SAleksey Makarov 		.max_adj        = 1000000000ull,
32299bbc4aeSYi Guo 		.n_ext_ts       = 1,
32399bbc4aeSYi Guo 		.n_pins         = 1,
324c9c12d33SAleksey Makarov 		.pps            = 0,
32599bbc4aeSYi Guo 		.pin_config     = &ptp_ptr->extts_config,
326c9c12d33SAleksey Makarov 		.adjfine        = otx2_ptp_adjfine,
327c9c12d33SAleksey Makarov 		.adjtime        = otx2_ptp_adjtime,
328c9c12d33SAleksey Makarov 		.gettime64      = otx2_ptp_gettime,
329c9c12d33SAleksey Makarov 		.settime64      = otx2_ptp_settime,
330c9c12d33SAleksey Makarov 		.enable         = otx2_ptp_enable,
33199bbc4aeSYi Guo 		.verify         = otx2_ptp_verify_pin,
332c9c12d33SAleksey Makarov 	};
333c9c12d33SAleksey Makarov 
33499bbc4aeSYi Guo 	INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check);
33599bbc4aeSYi Guo 
336c9c12d33SAleksey Makarov 	ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev);
337c9c12d33SAleksey Makarov 	if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) {
338c9c12d33SAleksey Makarov 		err = ptp_ptr->ptp_clock ?
339c9c12d33SAleksey Makarov 		      PTR_ERR(ptp_ptr->ptp_clock) : -ENODEV;
340c9c12d33SAleksey Makarov 		kfree(ptp_ptr);
341c9c12d33SAleksey Makarov 		goto error;
342c9c12d33SAleksey Makarov 	}
343c9c12d33SAleksey Makarov 
34474c1b233SNaveen Mamindlapalli 	if (is_dev_otx2(pfvf->pdev)) {
34574c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_rx_ptp_tstmp = &otx2_ptp_convert_rx_timestamp;
34674c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_tx_ptp_tstmp = &otx2_ptp_convert_tx_timestamp;
34774c1b233SNaveen Mamindlapalli 	} else {
34874c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_rx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
34974c1b233SNaveen Mamindlapalli 		ptp_ptr->convert_tx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
35074c1b233SNaveen Mamindlapalli 	}
35174c1b233SNaveen Mamindlapalli 
3522958d17aSHariprasad Kelam 	INIT_DELAYED_WORK(&ptp_ptr->synctstamp_work, otx2_sync_tstamp);
3532958d17aSHariprasad Kelam 
354c9c12d33SAleksey Makarov 	pfvf->ptp = ptp_ptr;
355c9c12d33SAleksey Makarov 
356c9c12d33SAleksey Makarov error:
357c9c12d33SAleksey Makarov 	return err;
358c9c12d33SAleksey Makarov }
3590e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_init);
360c9c12d33SAleksey Makarov 
361c9c12d33SAleksey Makarov void otx2_ptp_destroy(struct otx2_nic *pfvf)
362c9c12d33SAleksey Makarov {
363c9c12d33SAleksey Makarov 	struct otx2_ptp *ptp = pfvf->ptp;
364c9c12d33SAleksey Makarov 
365c9c12d33SAleksey Makarov 	if (!ptp)
366c9c12d33SAleksey Makarov 		return;
367c9c12d33SAleksey Makarov 
3682958d17aSHariprasad Kelam 	cancel_delayed_work(&pfvf->ptp->synctstamp_work);
3692958d17aSHariprasad Kelam 
370c9c12d33SAleksey Makarov 	ptp_clock_unregister(ptp->ptp_clock);
371c9c12d33SAleksey Makarov 	kfree(ptp);
372c9c12d33SAleksey Makarov 	pfvf->ptp = NULL;
373c9c12d33SAleksey Makarov }
3740e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_destroy);
375c9c12d33SAleksey Makarov 
376c9c12d33SAleksey Makarov int otx2_ptp_clock_index(struct otx2_nic *pfvf)
377c9c12d33SAleksey Makarov {
378c9c12d33SAleksey Makarov 	if (!pfvf->ptp)
379c9c12d33SAleksey Makarov 		return -ENODEV;
380c9c12d33SAleksey Makarov 
381c9c12d33SAleksey Makarov 	return ptp_clock_index(pfvf->ptp->ptp_clock);
382c9c12d33SAleksey Makarov }
3830e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_clock_index);
384c9c12d33SAleksey Makarov 
385c9c12d33SAleksey Makarov int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns)
386c9c12d33SAleksey Makarov {
387c9c12d33SAleksey Makarov 	if (!pfvf->ptp)
388c9c12d33SAleksey Makarov 		return -ENODEV;
389c9c12d33SAleksey Makarov 
390c9c12d33SAleksey Makarov 	*tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
391c9c12d33SAleksey Makarov 
392c9c12d33SAleksey Makarov 	return 0;
393c9c12d33SAleksey Makarov }
3940e9e7598SArnd Bergmann EXPORT_SYMBOL_GPL(otx2_ptp_tstamp2time);
3950e9e7598SArnd Bergmann 
3960e9e7598SArnd Bergmann MODULE_AUTHOR("Sunil Goutham <sgoutham@marvell.com>");
3970e9e7598SArnd Bergmann MODULE_DESCRIPTION("Marvell RVU NIC PTP Driver");
3980e9e7598SArnd Bergmann MODULE_LICENSE("GPL v2");
399