Lines Matching +full:poll +full:- +full:period

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PTP 1588 clock support - character device implementation.
9 #include <linux/posix-clock.h>
10 #include <linux/poll.h>
34 err = ops->enable(ops, &rq, 0); in ptp_disable_pinfunc()
39 err = ops->enable(ops, &rq, 0); in ptp_disable_pinfunc()
44 return -EINVAL; in ptp_disable_pinfunc()
53 struct ptp_clock_info *info = ptp->info; in ptp_set_pinfunc()
54 struct ptp_pin_desc *pin1 = NULL, *pin2 = &info->pin_config[pin]; in ptp_set_pinfunc()
58 for (i = 0; i < info->n_pins; i++) { in ptp_set_pinfunc()
59 if (info->pin_config[i].func == func && in ptp_set_pinfunc()
60 info->pin_config[i].chan == chan) { in ptp_set_pinfunc()
61 pin1 = &info->pin_config[i]; in ptp_set_pinfunc()
73 if (chan >= info->n_ext_ts) in ptp_set_pinfunc()
74 return -EINVAL; in ptp_set_pinfunc()
77 if (chan >= info->n_per_out) in ptp_set_pinfunc()
78 return -EINVAL; in ptp_set_pinfunc()
82 return -EINVAL; in ptp_set_pinfunc()
85 return -EINVAL; in ptp_set_pinfunc()
88 if (info->verify(info, pin, func, chan)) { in ptp_set_pinfunc()
91 return -EOPNOTSUPP; in ptp_set_pinfunc()
97 pin1->func = PTP_PF_NONE; in ptp_set_pinfunc()
98 pin1->chan = 0; in ptp_set_pinfunc()
100 ptp_disable_pinfunc(info, pin2->func, pin2->chan); in ptp_set_pinfunc()
101 pin2->func = func; in ptp_set_pinfunc()
102 pin2->chan = chan; in ptp_set_pinfunc()
109 struct ptp_clock *ptp = container_of(pccontext->clk, struct ptp_clock, clock); in ptp_open()
115 return -EINVAL; in ptp_open()
116 queue->mask = bitmap_alloc(PTP_MAX_CHANNELS, GFP_KERNEL); in ptp_open()
117 if (!queue->mask) { in ptp_open()
119 return -EINVAL; in ptp_open()
121 bitmap_set(queue->mask, 0, PTP_MAX_CHANNELS); in ptp_open()
122 spin_lock_init(&queue->lock); in ptp_open()
123 scoped_guard(spinlock_irq, &ptp->tsevqs_lock) in ptp_open()
124 list_add_tail(&queue->qlist, &ptp->tsevqs); in ptp_open()
125 pccontext->private_clkdata = queue; in ptp_open()
129 queue->debugfs_instance = in ptp_open()
130 debugfs_create_dir(debugfsname, ptp->debugfs_root); in ptp_open()
131 queue->dfs_bitmap.array = (u32 *)queue->mask; in ptp_open()
132 queue->dfs_bitmap.n_elements = in ptp_open()
134 debugfs_create_u32_array("mask", 0444, queue->debugfs_instance, in ptp_open()
135 &queue->dfs_bitmap); in ptp_open()
142 struct timestamp_event_queue *queue = pccontext->private_clkdata; in ptp_release()
144 container_of(pccontext->clk, struct ptp_clock, clock); in ptp_release()
146 debugfs_remove(queue->debugfs_instance); in ptp_release()
147 pccontext->private_clkdata = NULL; in ptp_release()
148 scoped_guard(spinlock_irq, &ptp->tsevqs_lock) in ptp_release()
149 list_del(&queue->qlist); in ptp_release()
150 bitmap_free(queue->mask); in ptp_release()
158 .max_adj = ptp->info->max_adj, in ptp_clock_getcaps()
159 .n_alarm = ptp->info->n_alarm, in ptp_clock_getcaps()
160 .n_ext_ts = ptp->info->n_ext_ts, in ptp_clock_getcaps()
161 .n_per_out = ptp->info->n_per_out, in ptp_clock_getcaps()
162 .pps = ptp->info->pps, in ptp_clock_getcaps()
163 .n_pins = ptp->info->n_pins, in ptp_clock_getcaps()
164 .cross_timestamping = ptp->info->getcrosststamp != NULL, in ptp_clock_getcaps()
165 .adjust_phase = ptp->info->adjphase != NULL && in ptp_clock_getcaps()
166 ptp->info->getmaxphase != NULL, in ptp_clock_getcaps()
170 caps.max_phase_adj = ptp->info->getmaxphase(ptp->info); in ptp_clock_getcaps()
172 return copy_to_user(arg, &caps, sizeof(caps)) ? -EFAULT : 0; in ptp_clock_getcaps()
178 struct ptp_clock_info *ops = ptp->info; in ptp_extts_request()
182 return -EFAULT; in ptp_extts_request()
190 return -EINVAL; in ptp_extts_request()
195 return -EINVAL; in ptp_extts_request()
201 if (req.extts.index >= ops->n_ext_ts) in ptp_extts_request()
202 return -EINVAL; in ptp_extts_request()
204 supported_extts_flags = ptp->info->supported_extts_flags; in ptp_extts_request()
215 return -EOPNOTSUPP; in ptp_extts_request()
217 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux) in ptp_extts_request()
218 return ops->enable(ops, &req, req.extts.flags & PTP_ENABLE_FEATURE ? 1 : 0); in ptp_extts_request()
225 struct ptp_clock_info *ops = ptp->info; in ptp_perout_request()
228 return -EFAULT; in ptp_perout_request()
231 if (perout->flags & ~PTP_PEROUT_VALID_FLAGS) in ptp_perout_request()
232 return -EINVAL; in ptp_perout_request()
239 if (!(perout->flags & PTP_PEROUT_DUTY_CYCLE) && in ptp_perout_request()
240 !mem_is_zero(perout->rsv, sizeof(perout->rsv))) in ptp_perout_request()
241 return -EINVAL; in ptp_perout_request()
243 if (perout->flags & PTP_PEROUT_DUTY_CYCLE) { in ptp_perout_request()
245 if (perout->on.sec > perout->period.sec || in ptp_perout_request()
246 (perout->on.sec == perout->period.sec && in ptp_perout_request()
247 perout->on.nsec > perout->period.nsec)) in ptp_perout_request()
248 return -ERANGE; in ptp_perout_request()
251 if (perout->flags & PTP_PEROUT_PHASE) { in ptp_perout_request()
253 * The phase should be specified modulo the period, in ptp_perout_request()
254 * therefore anything equal or larger than 1 period in ptp_perout_request()
257 if (perout->phase.sec > perout->period.sec || in ptp_perout_request()
258 (perout->phase.sec == perout->period.sec && in ptp_perout_request()
259 perout->phase.nsec >= perout->period.nsec)) in ptp_perout_request()
260 return -ERANGE; in ptp_perout_request()
263 perout->flags &= PTP_PEROUT_V1_VALID_FLAGS; in ptp_perout_request()
264 memset(perout->rsv, 0, sizeof(perout->rsv)); in ptp_perout_request()
267 if (perout->index >= ops->n_per_out) in ptp_perout_request()
268 return -EINVAL; in ptp_perout_request()
269 if (perout->flags & ~ops->supported_perout_flags) in ptp_perout_request()
270 return -EOPNOTSUPP; in ptp_perout_request()
272 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux) in ptp_perout_request()
273 return ops->enable(ops, &req, perout->period.sec || perout->period.nsec); in ptp_perout_request()
279 struct ptp_clock_info *ops = ptp->info; in ptp_enable_pps()
282 return -EPERM; in ptp_enable_pps()
284 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux) in ptp_enable_pps()
285 return ops->enable(ops, &req, enable); in ptp_enable_pps()
295 if (!ptp->info->getcrosststamp) in ptp_sys_offset_precise()
296 return -EOPNOTSUPP; in ptp_sys_offset_precise()
298 err = ptp->info->getcrosststamp(ptp->info, &xtstamp); in ptp_sys_offset_precise()
313 return copy_to_user(arg, &precise_offset, sizeof(precise_offset)) ? -EFAULT : 0; in ptp_sys_offset_precise()
321 if (!ptp->info->gettimex64) in ptp_sys_offset_extended()
322 return -EOPNOTSUPP; in ptp_sys_offset_extended()
328 if (extoff->n_samples > PTP_MAX_SAMPLES || extoff->rsv[0] || extoff->rsv[1]) in ptp_sys_offset_extended()
329 return -EINVAL; in ptp_sys_offset_extended()
331 switch (extoff->clockid) { in ptp_sys_offset_extended()
341 return -EINVAL; in ptp_sys_offset_extended()
344 sts.clockid = extoff->clockid; in ptp_sys_offset_extended()
345 for (unsigned int i = 0; i < extoff->n_samples; i++) { in ptp_sys_offset_extended()
349 err = ptp->info->gettimex64(ptp->info, &ts, &sts); in ptp_sys_offset_extended()
355 return -EINVAL; in ptp_sys_offset_extended()
357 extoff->ts[i][0].sec = sts.pre_ts.tv_sec; in ptp_sys_offset_extended()
358 extoff->ts[i][0].nsec = sts.pre_ts.tv_nsec; in ptp_sys_offset_extended()
359 extoff->ts[i][1].sec = ts.tv_sec; in ptp_sys_offset_extended()
360 extoff->ts[i][1].nsec = ts.tv_nsec; in ptp_sys_offset_extended()
361 extoff->ts[i][2].sec = sts.post_ts.tv_sec; in ptp_sys_offset_extended()
362 extoff->ts[i][2].nsec = sts.post_ts.tv_nsec; in ptp_sys_offset_extended()
365 return copy_to_user(arg, extoff, sizeof(*extoff)) ? -EFAULT : 0; in ptp_sys_offset_extended()
378 if (sysoff->n_samples > PTP_MAX_SAMPLES) in ptp_sys_offset()
379 return -EINVAL; in ptp_sys_offset()
381 pct = &sysoff->ts[0]; in ptp_sys_offset()
382 for (unsigned int i = 0; i < sysoff->n_samples; i++) { in ptp_sys_offset()
383 struct ptp_clock_info *ops = ptp->info; in ptp_sys_offset()
387 pct->sec = ts.tv_sec; in ptp_sys_offset()
388 pct->nsec = ts.tv_nsec; in ptp_sys_offset()
390 if (ops->gettimex64) in ptp_sys_offset()
391 err = ops->gettimex64(ops, &ts, NULL); in ptp_sys_offset()
393 err = ops->gettime64(ops, &ts); in ptp_sys_offset()
396 pct->sec = ts.tv_sec; in ptp_sys_offset()
397 pct->nsec = ts.tv_nsec; in ptp_sys_offset()
401 pct->sec = ts.tv_sec; in ptp_sys_offset()
402 pct->nsec = ts.tv_nsec; in ptp_sys_offset()
404 return copy_to_user(arg, sysoff, sizeof(*sysoff)) ? -EFAULT : 0; in ptp_sys_offset()
409 struct ptp_clock_info *ops = ptp->info; in ptp_pin_getfunc()
413 return -EFAULT; in ptp_pin_getfunc()
416 return -EINVAL; in ptp_pin_getfunc()
418 if (pd.index >= ops->n_pins) in ptp_pin_getfunc()
419 return -EINVAL; in ptp_pin_getfunc()
421 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux) in ptp_pin_getfunc()
422 pd = ops->pin_config[array_index_nospec(pd.index, ops->n_pins)]; in ptp_pin_getfunc()
424 return copy_to_user(arg, &pd, sizeof(pd)) ? -EFAULT : 0; in ptp_pin_getfunc()
429 struct ptp_clock_info *ops = ptp->info; in ptp_pin_setfunc()
434 return -EFAULT; in ptp_pin_setfunc()
437 return -EINVAL; in ptp_pin_setfunc()
439 if (pd.index >= ops->n_pins) in ptp_pin_setfunc()
440 return -EINVAL; in ptp_pin_setfunc()
442 pin_index = array_index_nospec(pd.index, ops->n_pins); in ptp_pin_setfunc()
443 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux) in ptp_pin_setfunc()
449 bitmap_clear(tsevq->mask, 0, PTP_MAX_CHANNELS); in ptp_mask_clear_all()
458 return -EFAULT; in ptp_mask_en_single()
460 return -EFAULT; in ptp_mask_en_single()
461 set_bit(channel, tsevq->mask); in ptp_mask_en_single()
468 struct ptp_clock *ptp = container_of(pccontext->clk, struct ptp_clock, clock); in ptp_ioctl()
482 if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) in ptp_ioctl()
483 return -EACCES; in ptp_ioctl()
488 if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) in ptp_ioctl()
489 return -EACCES; in ptp_ioctl()
494 if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) in ptp_ioctl()
495 return -EACCES; in ptp_ioctl()
516 if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) in ptp_ioctl()
517 return -EACCES; in ptp_ioctl()
521 return ptp_mask_clear_all(pccontext->private_clkdata); in ptp_ioctl()
524 return ptp_mask_en_single(pccontext->private_clkdata, argptr); in ptp_ioctl()
527 return -ENOTTY; in ptp_ioctl()
535 container_of(pccontext->clk, struct ptp_clock, clock); in ptp_poll()
538 queue = pccontext->private_clkdata; in ptp_poll()
542 poll_wait(fp, &ptp->tsev_wq, wait); in ptp_poll()
552 struct ptp_clock *ptp = container_of(pccontext->clk, struct ptp_clock, clock); in ptp_read()
557 queue = pccontext->private_clkdata; in ptp_read()
559 return -EINVAL; in ptp_read()
562 return -EINVAL; in ptp_read()
567 if (wait_event_interruptible(ptp->tsev_wq, ptp->defunct || queue_cnt(queue))) in ptp_read()
568 return -ERESTARTSYS; in ptp_read()
570 if (ptp->defunct) in ptp_read()
571 return -ENODEV; in ptp_read()
575 return -ENOMEM; in ptp_read()
577 scoped_guard(spinlock_irq, &queue->lock) { in ptp_read()
581 event[i] = queue->buf[queue->head]; in ptp_read()
583 WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS); in ptp_read()
590 result = -EFAULT; in ptp_read()