174ba9207SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 2d94ba80eSRichard Cochran /* 3d94ba80eSRichard Cochran * PTP 1588 clock support - private declarations for the core module. 4d94ba80eSRichard Cochran * 5d94ba80eSRichard Cochran * Copyright (C) 2010 OMICRON electronics GmbH 6d94ba80eSRichard Cochran */ 7d94ba80eSRichard Cochran #ifndef _PTP_PRIVATE_H_ 8d94ba80eSRichard Cochran #define _PTP_PRIVATE_H_ 9d94ba80eSRichard Cochran 10d94ba80eSRichard Cochran #include <linux/cdev.h> 11d94ba80eSRichard Cochran #include <linux/device.h> 12d9535cb7SGrygorii Strashko #include <linux/kthread.h> 13d94ba80eSRichard Cochran #include <linux/mutex.h> 14d94ba80eSRichard Cochran #include <linux/posix-clock.h> 15d94ba80eSRichard Cochran #include <linux/ptp_clock.h> 16d94ba80eSRichard Cochran #include <linux/ptp_clock_kernel.h> 17d94ba80eSRichard Cochran #include <linux/time.h> 18d94ba80eSRichard Cochran 19d94ba80eSRichard Cochran #define PTP_MAX_TIMESTAMPS 128 20d94ba80eSRichard Cochran #define PTP_BUF_TIMESTAMPS 30 2173f37068SYangbo Lu #define PTP_DEFAULT_MAX_VCLOCKS 20 22d94ba80eSRichard Cochran 23d94ba80eSRichard Cochran struct timestamp_event_queue { 24d94ba80eSRichard Cochran struct ptp_extts_event buf[PTP_MAX_TIMESTAMPS]; 25d94ba80eSRichard Cochran int head; 26d94ba80eSRichard Cochran int tail; 27d94ba80eSRichard Cochran spinlock_t lock; 28d94ba80eSRichard Cochran }; 29d94ba80eSRichard Cochran 30d94ba80eSRichard Cochran struct ptp_clock { 31d94ba80eSRichard Cochran struct posix_clock clock; 32a33121e5SVladis Dronov struct device dev; 33d94ba80eSRichard Cochran struct ptp_clock_info *info; 34d94ba80eSRichard Cochran dev_t devid; 35d94ba80eSRichard Cochran int index; /* index into clocks.map */ 36d94ba80eSRichard Cochran struct pps_device *pps_source; 3739a8cbd9SRichard Cochran long dialed_frequency; /* remembers the frequency adjustment */ 38d94ba80eSRichard Cochran struct timestamp_event_queue tsevq; /* simple fifo for time stamps */ 39d94ba80eSRichard Cochran struct mutex tsevq_mux; /* one process at a time reading the fifo */ 406092315dSRichard Cochran struct mutex pincfg_mux; /* protect concurrent info->pin_config access */ 41d94ba80eSRichard Cochran wait_queue_head_t tsev_wq; 42d94ba80eSRichard Cochran int defunct; /* tells readers to go away when clock is being removed */ 43653104d1SRichard Cochran struct device_attribute *pin_dev_attr; 44653104d1SRichard Cochran struct attribute **pin_attr; 45653104d1SRichard Cochran struct attribute_group pin_attr_group; 4685a66e55SDmitry Torokhov /* 1st entry is a pointer to the real group, 2nd is NULL terminator */ 4785a66e55SDmitry Torokhov const struct attribute_group *pin_attr_groups[2]; 48d9535cb7SGrygorii Strashko struct kthread_worker *kworker; 49d9535cb7SGrygorii Strashko struct kthread_delayed_work aux_work; 5073f37068SYangbo Lu unsigned int max_vclocks; 5173f37068SYangbo Lu unsigned int n_vclocks; 5244c494c8SYangbo Lu int *vclock_index; 5373f37068SYangbo Lu struct mutex n_vclocks_mux; /* protect concurrent n_vclocks access */ 5473f37068SYangbo Lu bool is_virtual_clock; 55d94ba80eSRichard Cochran }; 56d94ba80eSRichard Cochran 575d43f951SYangbo Lu #define info_to_vclock(d) container_of((d), struct ptp_vclock, info) 585d43f951SYangbo Lu #define cc_to_vclock(d) container_of((d), struct ptp_vclock, cc) 595d43f951SYangbo Lu #define dw_to_vclock(d) container_of((d), struct ptp_vclock, refresh_work) 605d43f951SYangbo Lu 615d43f951SYangbo Lu struct ptp_vclock { 625d43f951SYangbo Lu struct ptp_clock *pclock; 635d43f951SYangbo Lu struct ptp_clock_info info; 645d43f951SYangbo Lu struct ptp_clock *clock; 655d43f951SYangbo Lu struct cyclecounter cc; 665d43f951SYangbo Lu struct timecounter tc; 675d43f951SYangbo Lu spinlock_t lock; /* protects tc/cc */ 685d43f951SYangbo Lu }; 695d43f951SYangbo Lu 70d94ba80eSRichard Cochran /* 71d94ba80eSRichard Cochran * The function queue_cnt() is safe for readers to call without 72d94ba80eSRichard Cochran * holding q->lock. Readers use this function to verify that the queue 73d94ba80eSRichard Cochran * is nonempty before proceeding with a dequeue operation. The fact 74d94ba80eSRichard Cochran * that a writer might concurrently increment the tail does not 75d94ba80eSRichard Cochran * matter, since the queue remains nonempty nonetheless. 76d94ba80eSRichard Cochran */ 77d94ba80eSRichard Cochran static inline int queue_cnt(struct timestamp_event_queue *q) 78d94ba80eSRichard Cochran { 79d94ba80eSRichard Cochran int cnt = q->tail - q->head; 80d94ba80eSRichard Cochran return cnt < 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt; 81d94ba80eSRichard Cochran } 82d94ba80eSRichard Cochran 8373f37068SYangbo Lu /* Check if ptp virtual clock is in use */ 8473f37068SYangbo Lu static inline bool ptp_vclock_in_use(struct ptp_clock *ptp) 8573f37068SYangbo Lu { 8673f37068SYangbo Lu bool in_use = false; 8773f37068SYangbo Lu 8873f37068SYangbo Lu if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) 8973f37068SYangbo Lu return true; 9073f37068SYangbo Lu 9173f37068SYangbo Lu if (!ptp->is_virtual_clock && ptp->n_vclocks) 9273f37068SYangbo Lu in_use = true; 9373f37068SYangbo Lu 9473f37068SYangbo Lu mutex_unlock(&ptp->n_vclocks_mux); 9573f37068SYangbo Lu 9673f37068SYangbo Lu return in_use; 9773f37068SYangbo Lu } 9873f37068SYangbo Lu 99*acb288e8SYangbo Lu extern struct class *ptp_class; 100*acb288e8SYangbo Lu 101d94ba80eSRichard Cochran /* 102d94ba80eSRichard Cochran * see ptp_chardev.c 103d94ba80eSRichard Cochran */ 104d94ba80eSRichard Cochran 1056092315dSRichard Cochran /* caller must hold pincfg_mux */ 1066092315dSRichard Cochran int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, 1076092315dSRichard Cochran enum ptp_pin_function func, unsigned int chan); 1086092315dSRichard Cochran 109d94ba80eSRichard Cochran long ptp_ioctl(struct posix_clock *pc, 110d94ba80eSRichard Cochran unsigned int cmd, unsigned long arg); 111d94ba80eSRichard Cochran 112d94ba80eSRichard Cochran int ptp_open(struct posix_clock *pc, fmode_t fmode); 113d94ba80eSRichard Cochran 114d94ba80eSRichard Cochran ssize_t ptp_read(struct posix_clock *pc, 115d94ba80eSRichard Cochran uint flags, char __user *buf, size_t cnt); 116d94ba80eSRichard Cochran 117afc9a42bSAl Viro __poll_t ptp_poll(struct posix_clock *pc, 118d94ba80eSRichard Cochran struct file *fp, poll_table *wait); 119d94ba80eSRichard Cochran 120d94ba80eSRichard Cochran /* 121d94ba80eSRichard Cochran * see ptp_sysfs.c 122d94ba80eSRichard Cochran */ 123d94ba80eSRichard Cochran 1243499116bSGreg Kroah-Hartman extern const struct attribute_group *ptp_groups[]; 125d94ba80eSRichard Cochran 12685a66e55SDmitry Torokhov int ptp_populate_pin_groups(struct ptp_clock *ptp); 12785a66e55SDmitry Torokhov void ptp_cleanup_pin_groups(struct ptp_clock *ptp); 128d94ba80eSRichard Cochran 1295d43f951SYangbo Lu struct ptp_vclock *ptp_vclock_register(struct ptp_clock *pclock); 1305d43f951SYangbo Lu void ptp_vclock_unregister(struct ptp_vclock *vclock); 131d94ba80eSRichard Cochran #endif 132