1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * PTP 1588 clock support - sysfs interface. |
4 | * |
5 | * Copyright (C) 2010 OMICRON electronics GmbH |
6 | * Copyright 2021 NXP |
7 | */ |
8 | #include <linux/capability.h> |
9 | #include <linux/slab.h> |
10 | |
11 | #include "ptp_private.h" |
12 | |
13 | static ssize_t clock_name_show(struct device *dev, |
14 | struct device_attribute *attr, char *page) |
15 | { |
16 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
17 | return sysfs_emit(buf: page, fmt: "%s\n" , ptp->info->name); |
18 | } |
19 | static DEVICE_ATTR_RO(clock_name); |
20 | |
21 | static ssize_t max_phase_adjustment_show(struct device *dev, |
22 | struct device_attribute *attr, |
23 | char *page) |
24 | { |
25 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
26 | |
27 | return sysfs_emit(buf: page, fmt: "%d\n" , ptp->info->getmaxphase(ptp->info)); |
28 | } |
29 | static DEVICE_ATTR_RO(max_phase_adjustment); |
30 | |
31 | #define PTP_SHOW_INT(name, var) \ |
32 | static ssize_t var##_show(struct device *dev, \ |
33 | struct device_attribute *attr, char *page) \ |
34 | { \ |
35 | struct ptp_clock *ptp = dev_get_drvdata(dev); \ |
36 | return sysfs_emit(page, "%d\n", ptp->info->var); \ |
37 | } \ |
38 | static DEVICE_ATTR(name, 0444, var##_show, NULL); |
39 | |
40 | PTP_SHOW_INT(max_adjustment, max_adj); |
41 | PTP_SHOW_INT(n_alarms, n_alarm); |
42 | PTP_SHOW_INT(n_external_timestamps, n_ext_ts); |
43 | PTP_SHOW_INT(n_periodic_outputs, n_per_out); |
44 | PTP_SHOW_INT(n_programmable_pins, n_pins); |
45 | PTP_SHOW_INT(pps_available, pps); |
46 | |
47 | static ssize_t extts_enable_store(struct device *dev, |
48 | struct device_attribute *attr, |
49 | const char *buf, size_t count) |
50 | { |
51 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
52 | struct ptp_clock_info *ops = ptp->info; |
53 | struct ptp_clock_request req = { .type = PTP_CLK_REQ_EXTTS }; |
54 | int cnt, enable; |
55 | int err = -EINVAL; |
56 | |
57 | cnt = sscanf(buf, "%u %d" , &req.extts.index, &enable); |
58 | if (cnt != 2) |
59 | goto out; |
60 | if (req.extts.index >= ops->n_ext_ts) |
61 | goto out; |
62 | |
63 | err = ops->enable(ops, &req, enable ? 1 : 0); |
64 | if (err) |
65 | goto out; |
66 | |
67 | return count; |
68 | out: |
69 | return err; |
70 | } |
71 | static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store); |
72 | |
73 | static ssize_t extts_fifo_show(struct device *dev, |
74 | struct device_attribute *attr, char *page) |
75 | { |
76 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
77 | struct timestamp_event_queue *queue; |
78 | struct ptp_extts_event event; |
79 | unsigned long flags; |
80 | size_t qcnt; |
81 | int cnt = 0; |
82 | |
83 | cnt = list_count_nodes(head: &ptp->tsevqs); |
84 | if (cnt <= 0) |
85 | goto out; |
86 | |
87 | /* The sysfs fifo will always draw from the fist queue */ |
88 | queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue, |
89 | qlist); |
90 | |
91 | memset(&event, 0, sizeof(event)); |
92 | spin_lock_irqsave(&queue->lock, flags); |
93 | qcnt = queue_cnt(q: queue); |
94 | if (qcnt) { |
95 | event = queue->buf[queue->head]; |
96 | /* Paired with READ_ONCE() in queue_cnt() */ |
97 | WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS); |
98 | } |
99 | spin_unlock_irqrestore(lock: &queue->lock, flags); |
100 | |
101 | if (!qcnt) |
102 | goto out; |
103 | |
104 | cnt = sysfs_emit(buf: page, fmt: "%u %lld %u\n" , |
105 | event.index, event.t.sec, event.t.nsec); |
106 | out: |
107 | return cnt; |
108 | } |
109 | static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL); |
110 | |
111 | static ssize_t period_store(struct device *dev, |
112 | struct device_attribute *attr, |
113 | const char *buf, size_t count) |
114 | { |
115 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
116 | struct ptp_clock_info *ops = ptp->info; |
117 | struct ptp_clock_request req = { .type = PTP_CLK_REQ_PEROUT }; |
118 | int cnt, enable, err = -EINVAL; |
119 | |
120 | cnt = sscanf(buf, "%u %lld %u %lld %u" , &req.perout.index, |
121 | &req.perout.start.sec, &req.perout.start.nsec, |
122 | &req.perout.period.sec, &req.perout.period.nsec); |
123 | if (cnt != 5) |
124 | goto out; |
125 | if (req.perout.index >= ops->n_per_out) |
126 | goto out; |
127 | |
128 | enable = req.perout.period.sec || req.perout.period.nsec; |
129 | err = ops->enable(ops, &req, enable); |
130 | if (err) |
131 | goto out; |
132 | |
133 | return count; |
134 | out: |
135 | return err; |
136 | } |
137 | static DEVICE_ATTR(period, 0220, NULL, period_store); |
138 | |
139 | static ssize_t pps_enable_store(struct device *dev, |
140 | struct device_attribute *attr, |
141 | const char *buf, size_t count) |
142 | { |
143 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
144 | struct ptp_clock_info *ops = ptp->info; |
145 | struct ptp_clock_request req = { .type = PTP_CLK_REQ_PPS }; |
146 | int cnt, enable; |
147 | int err = -EINVAL; |
148 | |
149 | if (!capable(CAP_SYS_TIME)) |
150 | return -EPERM; |
151 | |
152 | cnt = sscanf(buf, "%d" , &enable); |
153 | if (cnt != 1) |
154 | goto out; |
155 | |
156 | err = ops->enable(ops, &req, enable ? 1 : 0); |
157 | if (err) |
158 | goto out; |
159 | |
160 | return count; |
161 | out: |
162 | return err; |
163 | } |
164 | static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store); |
165 | |
166 | static int unregister_vclock(struct device *dev, void *data) |
167 | { |
168 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
169 | struct ptp_clock_info *info = ptp->info; |
170 | struct ptp_vclock *vclock; |
171 | u32 *num = data; |
172 | |
173 | vclock = info_to_vclock(info); |
174 | dev_info(dev->parent, "delete virtual clock ptp%d\n" , |
175 | vclock->clock->index); |
176 | |
177 | ptp_vclock_unregister(vclock); |
178 | (*num)--; |
179 | |
180 | /* For break. Not error. */ |
181 | if (*num == 0) |
182 | return -EINVAL; |
183 | |
184 | return 0; |
185 | } |
186 | |
187 | static ssize_t n_vclocks_show(struct device *dev, |
188 | struct device_attribute *attr, char *page) |
189 | { |
190 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
191 | ssize_t size; |
192 | |
193 | if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) |
194 | return -ERESTARTSYS; |
195 | |
196 | size = sysfs_emit(buf: page, fmt: "%u\n" , ptp->n_vclocks); |
197 | |
198 | mutex_unlock(lock: &ptp->n_vclocks_mux); |
199 | |
200 | return size; |
201 | } |
202 | |
203 | static ssize_t n_vclocks_store(struct device *dev, |
204 | struct device_attribute *attr, |
205 | const char *buf, size_t count) |
206 | { |
207 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
208 | struct ptp_vclock *vclock; |
209 | int err = -EINVAL; |
210 | u32 num, i; |
211 | |
212 | if (kstrtou32(s: buf, base: 0, res: &num)) |
213 | return err; |
214 | |
215 | if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) |
216 | return -ERESTARTSYS; |
217 | |
218 | if (num > ptp->max_vclocks) { |
219 | dev_err(dev, "max value is %d\n" , ptp->max_vclocks); |
220 | goto out; |
221 | } |
222 | |
223 | /* Need to create more vclocks */ |
224 | if (num > ptp->n_vclocks) { |
225 | for (i = 0; i < num - ptp->n_vclocks; i++) { |
226 | vclock = ptp_vclock_register(pclock: ptp); |
227 | if (!vclock) |
228 | goto out; |
229 | |
230 | *(ptp->vclock_index + ptp->n_vclocks + i) = |
231 | vclock->clock->index; |
232 | |
233 | dev_info(dev, "new virtual clock ptp%d\n" , |
234 | vclock->clock->index); |
235 | } |
236 | } |
237 | |
238 | /* Need to delete vclocks */ |
239 | if (num < ptp->n_vclocks) { |
240 | i = ptp->n_vclocks - num; |
241 | device_for_each_child_reverse(dev, data: &i, |
242 | fn: unregister_vclock); |
243 | |
244 | for (i = 1; i <= ptp->n_vclocks - num; i++) |
245 | *(ptp->vclock_index + ptp->n_vclocks - i) = -1; |
246 | } |
247 | |
248 | /* Need to inform about changed physical clock behavior */ |
249 | if (!ptp->has_cycles) { |
250 | if (num == 0) |
251 | dev_info(dev, "only physical clock in use now\n" ); |
252 | else |
253 | dev_info(dev, "guarantee physical clock free running\n" ); |
254 | } |
255 | |
256 | ptp->n_vclocks = num; |
257 | mutex_unlock(lock: &ptp->n_vclocks_mux); |
258 | |
259 | return count; |
260 | out: |
261 | mutex_unlock(lock: &ptp->n_vclocks_mux); |
262 | return err; |
263 | } |
264 | static DEVICE_ATTR_RW(n_vclocks); |
265 | |
266 | static ssize_t max_vclocks_show(struct device *dev, |
267 | struct device_attribute *attr, char *page) |
268 | { |
269 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
270 | ssize_t size; |
271 | |
272 | size = sysfs_emit(buf: page, fmt: "%u\n" , ptp->max_vclocks); |
273 | |
274 | return size; |
275 | } |
276 | |
277 | static ssize_t max_vclocks_store(struct device *dev, |
278 | struct device_attribute *attr, |
279 | const char *buf, size_t count) |
280 | { |
281 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
282 | unsigned int *vclock_index; |
283 | int err = -EINVAL; |
284 | size_t size; |
285 | u32 max; |
286 | |
287 | if (kstrtou32(s: buf, base: 0, res: &max) || max == 0) |
288 | return -EINVAL; |
289 | |
290 | if (max == ptp->max_vclocks) |
291 | return count; |
292 | |
293 | if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) |
294 | return -ERESTARTSYS; |
295 | |
296 | if (max < ptp->n_vclocks) |
297 | goto out; |
298 | |
299 | size = sizeof(int) * max; |
300 | vclock_index = kzalloc(size, GFP_KERNEL); |
301 | if (!vclock_index) { |
302 | err = -ENOMEM; |
303 | goto out; |
304 | } |
305 | |
306 | size = sizeof(int) * ptp->n_vclocks; |
307 | memcpy(vclock_index, ptp->vclock_index, size); |
308 | |
309 | kfree(objp: ptp->vclock_index); |
310 | ptp->vclock_index = vclock_index; |
311 | ptp->max_vclocks = max; |
312 | |
313 | mutex_unlock(lock: &ptp->n_vclocks_mux); |
314 | |
315 | return count; |
316 | out: |
317 | mutex_unlock(lock: &ptp->n_vclocks_mux); |
318 | return err; |
319 | } |
320 | static DEVICE_ATTR_RW(max_vclocks); |
321 | |
322 | static struct attribute *ptp_attrs[] = { |
323 | &dev_attr_clock_name.attr, |
324 | |
325 | &dev_attr_max_adjustment.attr, |
326 | &dev_attr_max_phase_adjustment.attr, |
327 | &dev_attr_n_alarms.attr, |
328 | &dev_attr_n_external_timestamps.attr, |
329 | &dev_attr_n_periodic_outputs.attr, |
330 | &dev_attr_n_programmable_pins.attr, |
331 | &dev_attr_pps_available.attr, |
332 | |
333 | &dev_attr_extts_enable.attr, |
334 | &dev_attr_fifo.attr, |
335 | &dev_attr_period.attr, |
336 | &dev_attr_pps_enable.attr, |
337 | &dev_attr_n_vclocks.attr, |
338 | &dev_attr_max_vclocks.attr, |
339 | NULL |
340 | }; |
341 | |
342 | static umode_t ptp_is_attribute_visible(struct kobject *kobj, |
343 | struct attribute *attr, int n) |
344 | { |
345 | struct device *dev = kobj_to_dev(kobj); |
346 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
347 | struct ptp_clock_info *info = ptp->info; |
348 | umode_t mode = attr->mode; |
349 | |
350 | if (attr == &dev_attr_extts_enable.attr || |
351 | attr == &dev_attr_fifo.attr) { |
352 | if (!info->n_ext_ts) |
353 | mode = 0; |
354 | } else if (attr == &dev_attr_period.attr) { |
355 | if (!info->n_per_out) |
356 | mode = 0; |
357 | } else if (attr == &dev_attr_pps_enable.attr) { |
358 | if (!info->pps) |
359 | mode = 0; |
360 | } else if (attr == &dev_attr_n_vclocks.attr || |
361 | attr == &dev_attr_max_vclocks.attr) { |
362 | if (ptp->is_virtual_clock) |
363 | mode = 0; |
364 | } else if (attr == &dev_attr_max_phase_adjustment.attr) { |
365 | if (!info->adjphase || !info->getmaxphase) |
366 | mode = 0; |
367 | } |
368 | |
369 | return mode; |
370 | } |
371 | |
372 | static const struct attribute_group ptp_group = { |
373 | .is_visible = ptp_is_attribute_visible, |
374 | .attrs = ptp_attrs, |
375 | }; |
376 | |
377 | const struct attribute_group *ptp_groups[] = { |
378 | &ptp_group, |
379 | NULL |
380 | }; |
381 | |
382 | static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name) |
383 | { |
384 | int i; |
385 | for (i = 0; i < ptp->info->n_pins; i++) { |
386 | if (!strcmp(ptp->info->pin_config[i].name, name)) |
387 | return i; |
388 | } |
389 | return -1; |
390 | } |
391 | |
392 | static ssize_t ptp_pin_show(struct device *dev, struct device_attribute *attr, |
393 | char *page) |
394 | { |
395 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
396 | unsigned int func, chan; |
397 | int index; |
398 | |
399 | index = ptp_pin_name2index(ptp, name: attr->attr.name); |
400 | if (index < 0) |
401 | return -EINVAL; |
402 | |
403 | if (mutex_lock_interruptible(&ptp->pincfg_mux)) |
404 | return -ERESTARTSYS; |
405 | |
406 | func = ptp->info->pin_config[index].func; |
407 | chan = ptp->info->pin_config[index].chan; |
408 | |
409 | mutex_unlock(lock: &ptp->pincfg_mux); |
410 | |
411 | return sysfs_emit(buf: page, fmt: "%u %u\n" , func, chan); |
412 | } |
413 | |
414 | static ssize_t ptp_pin_store(struct device *dev, struct device_attribute *attr, |
415 | const char *buf, size_t count) |
416 | { |
417 | struct ptp_clock *ptp = dev_get_drvdata(dev); |
418 | unsigned int func, chan; |
419 | int cnt, err, index; |
420 | |
421 | cnt = sscanf(buf, "%u %u" , &func, &chan); |
422 | if (cnt != 2) |
423 | return -EINVAL; |
424 | |
425 | index = ptp_pin_name2index(ptp, name: attr->attr.name); |
426 | if (index < 0) |
427 | return -EINVAL; |
428 | |
429 | if (mutex_lock_interruptible(&ptp->pincfg_mux)) |
430 | return -ERESTARTSYS; |
431 | err = ptp_set_pinfunc(ptp, pin: index, func, chan); |
432 | mutex_unlock(lock: &ptp->pincfg_mux); |
433 | if (err) |
434 | return err; |
435 | |
436 | return count; |
437 | } |
438 | |
439 | int ptp_populate_pin_groups(struct ptp_clock *ptp) |
440 | { |
441 | struct ptp_clock_info *info = ptp->info; |
442 | int err = -ENOMEM, i, n_pins = info->n_pins; |
443 | |
444 | if (!n_pins) |
445 | return 0; |
446 | |
447 | ptp->pin_dev_attr = kcalloc(n: n_pins, size: sizeof(*ptp->pin_dev_attr), |
448 | GFP_KERNEL); |
449 | if (!ptp->pin_dev_attr) |
450 | goto no_dev_attr; |
451 | |
452 | ptp->pin_attr = kcalloc(n: 1 + n_pins, size: sizeof(*ptp->pin_attr), GFP_KERNEL); |
453 | if (!ptp->pin_attr) |
454 | goto no_pin_attr; |
455 | |
456 | for (i = 0; i < n_pins; i++) { |
457 | struct device_attribute *da = &ptp->pin_dev_attr[i]; |
458 | sysfs_attr_init(&da->attr); |
459 | da->attr.name = info->pin_config[i].name; |
460 | da->attr.mode = 0644; |
461 | da->show = ptp_pin_show; |
462 | da->store = ptp_pin_store; |
463 | ptp->pin_attr[i] = &da->attr; |
464 | } |
465 | |
466 | ptp->pin_attr_group.name = "pins" ; |
467 | ptp->pin_attr_group.attrs = ptp->pin_attr; |
468 | |
469 | ptp->pin_attr_groups[0] = &ptp->pin_attr_group; |
470 | |
471 | return 0; |
472 | |
473 | no_pin_attr: |
474 | kfree(objp: ptp->pin_dev_attr); |
475 | no_dev_attr: |
476 | return err; |
477 | } |
478 | |
479 | void ptp_cleanup_pin_groups(struct ptp_clock *ptp) |
480 | { |
481 | kfree(objp: ptp->pin_attr); |
482 | kfree(objp: ptp->pin_dev_attr); |
483 | } |
484 | |