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; 1760c69466SXabier Marquiegui struct posix_clock_context; 180606f422SRichard Cochran 190606f422SRichard Cochran /** 200606f422SRichard Cochran * struct posix_clock_operations - functional interface to the clock 210606f422SRichard Cochran * 220606f422SRichard Cochran * Every posix clock is represented by a character device. Drivers may 230606f422SRichard Cochran * optionally offer extended capabilities by implementing the 240606f422SRichard Cochran * character device methods. The character device file operations are 250606f422SRichard Cochran * first handled by the clock device layer, then passed on to the 260606f422SRichard Cochran * driver by calling these functions. 270606f422SRichard Cochran * 280606f422SRichard Cochran * @owner: The clock driver should set to THIS_MODULE 290606f422SRichard Cochran * @clock_adjtime: Adjust the clock 300606f422SRichard Cochran * @clock_gettime: Read the current time 310606f422SRichard Cochran * @clock_getres: Get the clock resolution 320606f422SRichard Cochran * @clock_settime: Set the current time value 330606f422SRichard Cochran * @open: Optional character device open method 340606f422SRichard Cochran * @release: Optional character device release method 350606f422SRichard Cochran * @ioctl: Optional character device ioctl method 360606f422SRichard Cochran * @read: Optional character device read method 370606f422SRichard Cochran * @poll: Optional character device poll method 380606f422SRichard Cochran */ 390606f422SRichard Cochran struct posix_clock_operations { 400606f422SRichard Cochran struct module *owner; 410606f422SRichard Cochran 42ead25417SDeepa Dinamani int (*clock_adjtime)(struct posix_clock *pc, struct __kernel_timex *tx); 430606f422SRichard Cochran 44d340266eSDeepa Dinamani int (*clock_gettime)(struct posix_clock *pc, struct timespec64 *ts); 450606f422SRichard Cochran 46d340266eSDeepa Dinamani int (*clock_getres) (struct posix_clock *pc, struct timespec64 *ts); 470606f422SRichard Cochran 480606f422SRichard Cochran int (*clock_settime)(struct posix_clock *pc, 49d340266eSDeepa Dinamani const struct timespec64 *ts); 500606f422SRichard Cochran 510606f422SRichard Cochran /* 520606f422SRichard Cochran * Optional character device methods: 530606f422SRichard Cochran */ 5460c69466SXabier Marquiegui long (*ioctl)(struct posix_clock_context *pccontext, unsigned int cmd, 5560c69466SXabier Marquiegui unsigned long arg); 560606f422SRichard Cochran 5760c69466SXabier Marquiegui int (*open)(struct posix_clock_context *pccontext, fmode_t f_mode); 580606f422SRichard Cochran 5960c69466SXabier Marquiegui __poll_t (*poll)(struct posix_clock_context *pccontext, struct file *file, 6060c69466SXabier Marquiegui poll_table *wait); 610606f422SRichard Cochran 6260c69466SXabier Marquiegui int (*release)(struct posix_clock_context *pccontext); 630606f422SRichard Cochran 6460c69466SXabier Marquiegui ssize_t (*read)(struct posix_clock_context *pccontext, uint flags, 6560c69466SXabier Marquiegui char __user *buf, size_t cnt); 660606f422SRichard Cochran }; 670606f422SRichard Cochran 680606f422SRichard Cochran /** 690606f422SRichard Cochran * struct posix_clock - represents a dynamic posix clock 700606f422SRichard Cochran * 710606f422SRichard Cochran * @ops: Functional interface to the clock 720606f422SRichard Cochran * @cdev: Character device instance for this clock 73a33121e5SVladis Dronov * @dev: Pointer to the clock's device. 741791f881SRichard Cochran * @rwsem: Protects the 'zombie' field from concurrent access. 750606f422SRichard Cochran * @zombie: If 'zombie' is true, then the hardware has disappeared. 760606f422SRichard Cochran * 770606f422SRichard Cochran * Drivers should embed their struct posix_clock within a private 780606f422SRichard Cochran * structure, obtaining a reference to it during callbacks using 790606f422SRichard Cochran * container_of(). 80a33121e5SVladis Dronov * 81a33121e5SVladis Dronov * Drivers should supply an initialized but not exposed struct device 82a33121e5SVladis Dronov * to posix_clock_register(). It is used to manage lifetime of the 83a33121e5SVladis Dronov * driver's private structure. It's 'release' field should be set to 84a33121e5SVladis Dronov * a release function for this private structure. 850606f422SRichard Cochran */ 860606f422SRichard Cochran struct posix_clock { 870606f422SRichard Cochran struct posix_clock_operations ops; 880606f422SRichard Cochran struct cdev cdev; 89a33121e5SVladis Dronov struct device *dev; 901791f881SRichard Cochran struct rw_semaphore rwsem; 910606f422SRichard Cochran bool zombie; 920606f422SRichard Cochran }; 930606f422SRichard Cochran 940606f422SRichard Cochran /** 9560c69466SXabier Marquiegui * struct posix_clock_context - represents clock file operations context 9660c69466SXabier Marquiegui * 9760c69466SXabier Marquiegui * @clk: Pointer to the clock 98*e859d375SWojtek Wasko * @fp: Pointer to the file used to open the clock 9960c69466SXabier Marquiegui * @private_clkdata: Pointer to user data 10060c69466SXabier Marquiegui * 10160c69466SXabier Marquiegui * Drivers should use struct posix_clock_context during specific character 102*e859d375SWojtek Wasko * device file operation methods to access the posix clock. In particular, 103*e859d375SWojtek Wasko * the file pointer can be used to verify correct access mode for ioctl() 104*e859d375SWojtek Wasko * calls. 10560c69466SXabier Marquiegui * 10660c69466SXabier Marquiegui * Drivers can store a private data structure during the open operation 10760c69466SXabier Marquiegui * if they have specific information that is required in other file 10860c69466SXabier Marquiegui * operations. 10960c69466SXabier Marquiegui */ 11060c69466SXabier Marquiegui struct posix_clock_context { 11160c69466SXabier Marquiegui struct posix_clock *clk; 112*e859d375SWojtek Wasko struct file *fp; 11360c69466SXabier Marquiegui void *private_clkdata; 11460c69466SXabier Marquiegui }; 11560c69466SXabier Marquiegui 11660c69466SXabier Marquiegui /** 1170606f422SRichard Cochran * posix_clock_register() - register a new clock 118a33121e5SVladis Dronov * @clk: Pointer to the clock. Caller must provide 'ops' field 119a33121e5SVladis Dronov * @dev: Pointer to the initialized device. Caller must provide 120a33121e5SVladis Dronov * 'release' field 1210606f422SRichard Cochran * 1220606f422SRichard Cochran * A clock driver calls this function to register itself with the 1230606f422SRichard Cochran * clock device subsystem. If 'clk' points to dynamically allocated 1240606f422SRichard Cochran * memory, then the caller must provide a 'release' function to free 1250606f422SRichard Cochran * that memory. 1260606f422SRichard Cochran * 1270606f422SRichard Cochran * Returns zero on success, non-zero otherwise. 1280606f422SRichard Cochran */ 129a33121e5SVladis Dronov int posix_clock_register(struct posix_clock *clk, struct device *dev); 1300606f422SRichard Cochran 1310606f422SRichard Cochran /** 1320606f422SRichard Cochran * posix_clock_unregister() - unregister a clock 1330606f422SRichard Cochran * @clk: Clock instance previously registered via posix_clock_register() 1340606f422SRichard Cochran * 1350606f422SRichard Cochran * A clock driver calls this function to remove itself from the clock 1360606f422SRichard Cochran * device subsystem. The posix_clock itself will remain (in an 1370606f422SRichard Cochran * inactive state) until its reference count drops to zero, at which 1380606f422SRichard Cochran * point it will be deallocated with its 'release' method. 1390606f422SRichard Cochran */ 1400606f422SRichard Cochran void posix_clock_unregister(struct posix_clock *clk); 1410606f422SRichard Cochran 1420606f422SRichard Cochran #endif 143