174ba9207SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 20606f422SRichard Cochran /* 30606f422SRichard Cochran * posix-clock.h - support for dynamic clock devices 40606f422SRichard Cochran * 50606f422SRichard Cochran * Copyright (C) 2010 OMICRON electronics GmbH 60606f422SRichard Cochran */ 70606f422SRichard Cochran #ifndef _LINUX_POSIX_CLOCK_H_ 80606f422SRichard Cochran #define _LINUX_POSIX_CLOCK_H_ 90606f422SRichard Cochran 100606f422SRichard Cochran #include <linux/cdev.h> 110606f422SRichard Cochran #include <linux/fs.h> 120606f422SRichard Cochran #include <linux/poll.h> 130606f422SRichard Cochran #include <linux/posix-timers.h> 141791f881SRichard Cochran #include <linux/rwsem.h> 150606f422SRichard Cochran 160606f422SRichard Cochran struct posix_clock; 170606f422SRichard Cochran 180606f422SRichard Cochran /** 190606f422SRichard Cochran * struct posix_clock_operations - functional interface to the clock 200606f422SRichard Cochran * 210606f422SRichard Cochran * Every posix clock is represented by a character device. Drivers may 220606f422SRichard Cochran * optionally offer extended capabilities by implementing the 230606f422SRichard Cochran * character device methods. The character device file operations are 240606f422SRichard Cochran * first handled by the clock device layer, then passed on to the 250606f422SRichard Cochran * driver by calling these functions. 260606f422SRichard Cochran * 270606f422SRichard Cochran * @owner: The clock driver should set to THIS_MODULE 280606f422SRichard Cochran * @clock_adjtime: Adjust the clock 290606f422SRichard Cochran * @clock_gettime: Read the current time 300606f422SRichard Cochran * @clock_getres: Get the clock resolution 310606f422SRichard Cochran * @clock_settime: Set the current time value 320606f422SRichard Cochran * @open: Optional character device open method 330606f422SRichard Cochran * @release: Optional character device release method 340606f422SRichard Cochran * @ioctl: Optional character device ioctl method 350606f422SRichard Cochran * @read: Optional character device read method 360606f422SRichard Cochran * @poll: Optional character device poll method 370606f422SRichard Cochran */ 380606f422SRichard Cochran struct posix_clock_operations { 390606f422SRichard Cochran struct module *owner; 400606f422SRichard Cochran 41ead25417SDeepa Dinamani int (*clock_adjtime)(struct posix_clock *pc, struct __kernel_timex *tx); 420606f422SRichard Cochran 43d340266eSDeepa Dinamani int (*clock_gettime)(struct posix_clock *pc, struct timespec64 *ts); 440606f422SRichard Cochran 45d340266eSDeepa Dinamani int (*clock_getres) (struct posix_clock *pc, struct timespec64 *ts); 460606f422SRichard Cochran 470606f422SRichard Cochran int (*clock_settime)(struct posix_clock *pc, 48d340266eSDeepa Dinamani const struct timespec64 *ts); 490606f422SRichard Cochran 500606f422SRichard Cochran /* 510606f422SRichard Cochran * Optional character device methods: 520606f422SRichard Cochran */ 530606f422SRichard Cochran long (*ioctl) (struct posix_clock *pc, 540606f422SRichard Cochran unsigned int cmd, unsigned long arg); 550606f422SRichard Cochran 560606f422SRichard Cochran int (*open) (struct posix_clock *pc, fmode_t f_mode); 570606f422SRichard Cochran 58a3f8683bSAl Viro __poll_t (*poll) (struct posix_clock *pc, 590606f422SRichard Cochran struct file *file, poll_table *wait); 600606f422SRichard Cochran 610606f422SRichard Cochran int (*release) (struct posix_clock *pc); 620606f422SRichard Cochran 630606f422SRichard Cochran ssize_t (*read) (struct posix_clock *pc, 640606f422SRichard Cochran uint flags, char __user *buf, size_t cnt); 650606f422SRichard Cochran }; 660606f422SRichard Cochran 670606f422SRichard Cochran /** 680606f422SRichard Cochran * struct posix_clock - represents a dynamic posix clock 690606f422SRichard Cochran * 700606f422SRichard Cochran * @ops: Functional interface to the clock 710606f422SRichard Cochran * @cdev: Character device instance for this clock 72a33121e5SVladis Dronov * @dev: Pointer to the clock's device. 731791f881SRichard Cochran * @rwsem: Protects the 'zombie' field from concurrent access. 740606f422SRichard Cochran * @zombie: If 'zombie' is true, then the hardware has disappeared. 750606f422SRichard Cochran * 760606f422SRichard Cochran * Drivers should embed their struct posix_clock within a private 770606f422SRichard Cochran * structure, obtaining a reference to it during callbacks using 780606f422SRichard Cochran * container_of(). 79a33121e5SVladis Dronov * 80a33121e5SVladis Dronov * Drivers should supply an initialized but not exposed struct device 81a33121e5SVladis Dronov * to posix_clock_register(). It is used to manage lifetime of the 82a33121e5SVladis Dronov * driver's private structure. It's 'release' field should be set to 83a33121e5SVladis Dronov * a release function for this private structure. 840606f422SRichard Cochran */ 850606f422SRichard Cochran struct posix_clock { 860606f422SRichard Cochran struct posix_clock_operations ops; 870606f422SRichard Cochran struct cdev cdev; 88a33121e5SVladis Dronov struct device *dev; 891791f881SRichard Cochran struct rw_semaphore rwsem; 900606f422SRichard Cochran bool zombie; 910606f422SRichard Cochran }; 920606f422SRichard Cochran 930606f422SRichard Cochran /** 940606f422SRichard Cochran * posix_clock_register() - register a new clock 95a33121e5SVladis Dronov * @clk: Pointer to the clock. Caller must provide 'ops' field 96a33121e5SVladis Dronov * @dev: Pointer to the initialized device. Caller must provide 97a33121e5SVladis Dronov * 'release' field 980606f422SRichard Cochran * 990606f422SRichard Cochran * A clock driver calls this function to register itself with the 1000606f422SRichard Cochran * clock device subsystem. If 'clk' points to dynamically allocated 1010606f422SRichard Cochran * memory, then the caller must provide a 'release' function to free 1020606f422SRichard Cochran * that memory. 1030606f422SRichard Cochran * 1040606f422SRichard Cochran * Returns zero on success, non-zero otherwise. 1050606f422SRichard Cochran */ 106a33121e5SVladis Dronov int posix_clock_register(struct posix_clock *clk, struct device *dev); 1070606f422SRichard Cochran 1080606f422SRichard Cochran /** 1090606f422SRichard Cochran * posix_clock_unregister() - unregister a clock 1100606f422SRichard Cochran * @clk: Clock instance previously registered via posix_clock_register() 1110606f422SRichard Cochran * 1120606f422SRichard Cochran * A clock driver calls this function to remove itself from the clock 1130606f422SRichard Cochran * device subsystem. The posix_clock itself will remain (in an 1140606f422SRichard Cochran * inactive state) until its reference count drops to zero, at which 1150606f422SRichard Cochran * point it will be deallocated with its 'release' method. 1160606f422SRichard Cochran */ 1170606f422SRichard Cochran void posix_clock_unregister(struct posix_clock *clk); 1180606f422SRichard Cochran 1190606f422SRichard Cochran #endif 120