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