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