1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell RVU Ethernet driver
3  *
4  * Copyright (C) 2020 Marvell.
5  *
6  */
7 
8 #include <linux/module.h>
9 
10 #include "otx2_common.h"
11 #include "otx2_ptp.h"
12 
13 static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
14 {
15 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
16 					    ptp_info);
17 	struct ptp_req *req;
18 
19 	if (!ptp->nic)
20 		return -ENODEV;
21 
22 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
23 	if (!req)
24 		return -ENOMEM;
25 
26 	req->op = PTP_OP_ADJFINE;
27 	req->scaled_ppm = scaled_ppm;
28 
29 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
30 }
31 
32 static int ptp_set_thresh(struct otx2_ptp *ptp, u64 thresh)
33 {
34 	struct ptp_req *req;
35 
36 	if (!ptp->nic)
37 		return -ENODEV;
38 
39 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
40 	if (!req)
41 		return -ENOMEM;
42 
43 	req->op = PTP_OP_SET_THRESH;
44 	req->thresh = thresh;
45 
46 	return otx2_sync_mbox_msg(&ptp->nic->mbox);
47 }
48 
49 static u64 ptp_cc_read(const struct cyclecounter *cc)
50 {
51 	struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter);
52 	struct ptp_req *req;
53 	struct ptp_rsp *rsp;
54 	int err;
55 
56 	if (!ptp->nic)
57 		return 0;
58 
59 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
60 	if (!req)
61 		return 0;
62 
63 	req->op = PTP_OP_GET_CLOCK;
64 
65 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
66 	if (err)
67 		return 0;
68 
69 	rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
70 						  &req->hdr);
71 	if (IS_ERR(rsp))
72 		return 0;
73 
74 	return rsp->clk;
75 }
76 
77 static u64 ptp_tstmp_read(struct otx2_ptp *ptp)
78 {
79 	struct ptp_req *req;
80 	struct ptp_rsp *rsp;
81 	int err;
82 
83 	if (!ptp->nic)
84 		return 0;
85 
86 	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
87 	if (!req)
88 		return 0;
89 
90 	req->op = PTP_OP_GET_TSTMP;
91 
92 	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
93 	if (err)
94 		return 0;
95 
96 	rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
97 						  &req->hdr);
98 	if (IS_ERR(rsp))
99 		return 0;
100 
101 	return rsp->clk;
102 }
103 
104 static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
105 {
106 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
107 					    ptp_info);
108 	struct otx2_nic *pfvf = ptp->nic;
109 
110 	mutex_lock(&pfvf->mbox.lock);
111 	timecounter_adjtime(&ptp->time_counter, delta);
112 	mutex_unlock(&pfvf->mbox.lock);
113 
114 	return 0;
115 }
116 
117 static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info,
118 			    struct timespec64 *ts)
119 {
120 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
121 					    ptp_info);
122 	struct otx2_nic *pfvf = ptp->nic;
123 	u64 nsec;
124 
125 	mutex_lock(&pfvf->mbox.lock);
126 	nsec = timecounter_read(&ptp->time_counter);
127 	mutex_unlock(&pfvf->mbox.lock);
128 
129 	*ts = ns_to_timespec64(nsec);
130 
131 	return 0;
132 }
133 
134 static int otx2_ptp_settime(struct ptp_clock_info *ptp_info,
135 			    const struct timespec64 *ts)
136 {
137 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
138 					    ptp_info);
139 	struct otx2_nic *pfvf = ptp->nic;
140 	u64 nsec;
141 
142 	nsec = timespec64_to_ns(ts);
143 
144 	mutex_lock(&pfvf->mbox.lock);
145 	timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
146 	mutex_unlock(&pfvf->mbox.lock);
147 
148 	return 0;
149 }
150 
151 static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
152 			       enum ptp_pin_function func, unsigned int chan)
153 {
154 	switch (func) {
155 	case PTP_PF_NONE:
156 	case PTP_PF_EXTTS:
157 		break;
158 	case PTP_PF_PEROUT:
159 	case PTP_PF_PHYSYNC:
160 		return -1;
161 	}
162 	return 0;
163 }
164 
165 static void otx2_ptp_extts_check(struct work_struct *work)
166 {
167 	struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
168 					    extts_work.work);
169 	struct ptp_clock_event event;
170 	u64 tstmp, new_thresh;
171 
172 	mutex_lock(&ptp->nic->mbox.lock);
173 	tstmp = ptp_tstmp_read(ptp);
174 	mutex_unlock(&ptp->nic->mbox.lock);
175 
176 	if (tstmp != ptp->last_extts) {
177 		event.type = PTP_CLOCK_EXTTS;
178 		event.index = 0;
179 		event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp);
180 		ptp_clock_event(ptp->ptp_clock, &event);
181 		ptp->last_extts = tstmp;
182 
183 		new_thresh = tstmp % 500000000;
184 		if (ptp->thresh != new_thresh) {
185 			mutex_lock(&ptp->nic->mbox.lock);
186 			ptp_set_thresh(ptp, new_thresh);
187 			mutex_unlock(&ptp->nic->mbox.lock);
188 			ptp->thresh = new_thresh;
189 		}
190 	}
191 	schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
192 }
193 
194 static int otx2_ptp_enable(struct ptp_clock_info *ptp_info,
195 			   struct ptp_clock_request *rq, int on)
196 {
197 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
198 					    ptp_info);
199 	int pin;
200 
201 	if (!ptp->nic)
202 		return -ENODEV;
203 
204 	switch (rq->type) {
205 	case PTP_CLK_REQ_EXTTS:
206 		pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS,
207 				   rq->extts.index);
208 		if (pin < 0)
209 			return -EBUSY;
210 		if (on)
211 			schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
212 		else
213 			cancel_delayed_work_sync(&ptp->extts_work);
214 		return 0;
215 	default:
216 		break;
217 	}
218 	return -EOPNOTSUPP;
219 }
220 
221 int otx2_ptp_init(struct otx2_nic *pfvf)
222 {
223 	struct otx2_ptp *ptp_ptr;
224 	struct cyclecounter *cc;
225 	struct ptp_req *req;
226 	int err;
227 
228 	if (is_otx2_lbkvf(pfvf->pdev)) {
229 		pfvf->ptp = NULL;
230 		return 0;
231 	}
232 
233 	mutex_lock(&pfvf->mbox.lock);
234 	/* check if PTP block is available */
235 	req = otx2_mbox_alloc_msg_ptp_op(&pfvf->mbox);
236 	if (!req) {
237 		mutex_unlock(&pfvf->mbox.lock);
238 		return -ENOMEM;
239 	}
240 
241 	req->op = PTP_OP_GET_CLOCK;
242 
243 	err = otx2_sync_mbox_msg(&pfvf->mbox);
244 	if (err) {
245 		mutex_unlock(&pfvf->mbox.lock);
246 		return err;
247 	}
248 	mutex_unlock(&pfvf->mbox.lock);
249 
250 	ptp_ptr = kzalloc(sizeof(*ptp_ptr), GFP_KERNEL);
251 	if (!ptp_ptr) {
252 		err = -ENOMEM;
253 		goto error;
254 	}
255 
256 	ptp_ptr->nic = pfvf;
257 
258 	cc = &ptp_ptr->cycle_counter;
259 	cc->read = ptp_cc_read;
260 	cc->mask = CYCLECOUNTER_MASK(64);
261 	cc->mult = 1;
262 	cc->shift = 0;
263 
264 	timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
265 			 ktime_to_ns(ktime_get_real()));
266 
267 	snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP");
268 	ptp_ptr->extts_config.index = 0;
269 	ptp_ptr->extts_config.func = PTP_PF_NONE;
270 
271 	ptp_ptr->ptp_info = (struct ptp_clock_info) {
272 		.owner          = THIS_MODULE,
273 		.name           = "OcteonTX2 PTP",
274 		.max_adj        = 1000000000ull,
275 		.n_ext_ts       = 1,
276 		.n_pins         = 1,
277 		.pps            = 0,
278 		.pin_config     = &ptp_ptr->extts_config,
279 		.adjfine        = otx2_ptp_adjfine,
280 		.adjtime        = otx2_ptp_adjtime,
281 		.gettime64      = otx2_ptp_gettime,
282 		.settime64      = otx2_ptp_settime,
283 		.enable         = otx2_ptp_enable,
284 		.verify         = otx2_ptp_verify_pin,
285 	};
286 
287 	INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check);
288 
289 	ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev);
290 	if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) {
291 		err = ptp_ptr->ptp_clock ?
292 		      PTR_ERR(ptp_ptr->ptp_clock) : -ENODEV;
293 		kfree(ptp_ptr);
294 		goto error;
295 	}
296 
297 	pfvf->ptp = ptp_ptr;
298 
299 error:
300 	return err;
301 }
302 EXPORT_SYMBOL_GPL(otx2_ptp_init);
303 
304 void otx2_ptp_destroy(struct otx2_nic *pfvf)
305 {
306 	struct otx2_ptp *ptp = pfvf->ptp;
307 
308 	if (!ptp)
309 		return;
310 
311 	ptp_clock_unregister(ptp->ptp_clock);
312 	kfree(ptp);
313 	pfvf->ptp = NULL;
314 }
315 EXPORT_SYMBOL_GPL(otx2_ptp_destroy);
316 
317 int otx2_ptp_clock_index(struct otx2_nic *pfvf)
318 {
319 	if (!pfvf->ptp)
320 		return -ENODEV;
321 
322 	return ptp_clock_index(pfvf->ptp->ptp_clock);
323 }
324 EXPORT_SYMBOL_GPL(otx2_ptp_clock_index);
325 
326 int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns)
327 {
328 	if (!pfvf->ptp)
329 		return -ENODEV;
330 
331 	*tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
332 
333 	return 0;
334 }
335 EXPORT_SYMBOL_GPL(otx2_ptp_tstamp2time);
336 
337 MODULE_AUTHOR("Sunil Goutham <sgoutham@marvell.com>");
338 MODULE_DESCRIPTION("Marvell RVU NIC PTP Driver");
339 MODULE_LICENSE("GPL v2");
340