10606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran/* 20606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * posix-clock.h - support for dynamic clock devices 30606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 40606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * Copyright (C) 2010 OMICRON electronics GmbH 50606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 60606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * This program is free software; you can redistribute it and/or modify 70606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * it under the terms of the GNU General Public License as published by 80606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * the Free Software Foundation; either version 2 of the License, or 90606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * (at your option) any later version. 100606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 110606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * This program is distributed in the hope that it will be useful, 120606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * but WITHOUT ANY WARRANTY; without even the implied warranty of 130606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 140606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * GNU General Public License for more details. 150606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 160606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * You should have received a copy of the GNU General Public License 170606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * along with this program; if not, write to the Free Software 180606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 190606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran */ 200606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#ifndef _LINUX_POSIX_CLOCK_H_ 210606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#define _LINUX_POSIX_CLOCK_H_ 220606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 230606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#include <linux/cdev.h> 240606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#include <linux/fs.h> 250606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#include <linux/poll.h> 260606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#include <linux/posix-timers.h> 271791f881435fab951939ad700e947b66c062e083Richard Cochran#include <linux/rwsem.h> 280606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 290606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochranstruct posix_clock; 300606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 310606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran/** 320606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * struct posix_clock_operations - functional interface to the clock 330606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 340606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * Every posix clock is represented by a character device. Drivers may 350606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * optionally offer extended capabilities by implementing the 360606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * character device methods. The character device file operations are 370606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * first handled by the clock device layer, then passed on to the 380606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * driver by calling these functions. 390606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 400606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @owner: The clock driver should set to THIS_MODULE 410606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @clock_adjtime: Adjust the clock 420606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @clock_gettime: Read the current time 430606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @clock_getres: Get the clock resolution 440606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @clock_settime: Set the current time value 450606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @timer_create: Create a new timer 460606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @timer_delete: Remove a previously created timer 470606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @timer_gettime: Get remaining time and interval of a timer 4870f23fd66bc821a0e99647f70a809e277cc93c4cJustin P. Mattock * @timer_settime: Set a timer's initial expiration and interval 490606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @fasync: Optional character device fasync method 500606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @mmap: Optional character device mmap method 510606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @open: Optional character device open method 520606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @release: Optional character device release method 530606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @ioctl: Optional character device ioctl method 540606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @read: Optional character device read method 550606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @poll: Optional character device poll method 560606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran */ 570606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochranstruct posix_clock_operations { 580606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct module *owner; 590606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 600606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*clock_adjtime)(struct posix_clock *pc, struct timex *tx); 610606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 620606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*clock_gettime)(struct posix_clock *pc, struct timespec *ts); 630606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 640606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*clock_getres) (struct posix_clock *pc, struct timespec *ts); 650606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 660606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*clock_settime)(struct posix_clock *pc, 670606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran const struct timespec *ts); 680606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 690606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*timer_create) (struct posix_clock *pc, struct k_itimer *kit); 700606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 710606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*timer_delete) (struct posix_clock *pc, struct k_itimer *kit); 720606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 730606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran void (*timer_gettime)(struct posix_clock *pc, 740606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct k_itimer *kit, struct itimerspec *tsp); 750606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 760606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*timer_settime)(struct posix_clock *pc, 770606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct k_itimer *kit, int flags, 780606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct itimerspec *tsp, struct itimerspec *old); 790606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran /* 800606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * Optional character device methods: 810606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran */ 820606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*fasync) (struct posix_clock *pc, 830606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int fd, struct file *file, int on); 840606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 850606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran long (*ioctl) (struct posix_clock *pc, 860606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran unsigned int cmd, unsigned long arg); 870606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 880606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*mmap) (struct posix_clock *pc, 890606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct vm_area_struct *vma); 900606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 910606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*open) (struct posix_clock *pc, fmode_t f_mode); 920606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 930606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran uint (*poll) (struct posix_clock *pc, 940606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct file *file, poll_table *wait); 950606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 960606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran int (*release) (struct posix_clock *pc); 970606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 980606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran ssize_t (*read) (struct posix_clock *pc, 990606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran uint flags, char __user *buf, size_t cnt); 1000606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran}; 1010606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 1020606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran/** 1030606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * struct posix_clock - represents a dynamic posix clock 1040606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 1050606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @ops: Functional interface to the clock 1060606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @cdev: Character device instance for this clock 1070606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @kref: Reference count. 1081791f881435fab951939ad700e947b66c062e083Richard Cochran * @rwsem: Protects the 'zombie' field from concurrent access. 1090606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @zombie: If 'zombie' is true, then the hardware has disappeared. 1100606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @release: A function to free the structure when the reference count reaches 1110606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * zero. May be NULL if structure is statically allocated. 1120606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 1130606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * Drivers should embed their struct posix_clock within a private 1140606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * structure, obtaining a reference to it during callbacks using 1150606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * container_of(). 1160606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran */ 1170606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochranstruct posix_clock { 1180606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct posix_clock_operations ops; 1190606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct cdev cdev; 1200606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran struct kref kref; 1211791f881435fab951939ad700e947b66c062e083Richard Cochran struct rw_semaphore rwsem; 1220606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran bool zombie; 1230606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran void (*release)(struct posix_clock *clk); 1240606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran}; 1250606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 1260606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran/** 1270606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * posix_clock_register() - register a new clock 1280606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @clk: Pointer to the clock. Caller must provide 'ops' and 'release' 1290606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @devid: Allocated device id 1300606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 1310606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * A clock driver calls this function to register itself with the 1320606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * clock device subsystem. If 'clk' points to dynamically allocated 1330606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * memory, then the caller must provide a 'release' function to free 1340606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * that memory. 1350606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 1360606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * Returns zero on success, non-zero otherwise. 1370606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran */ 1380606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochranint posix_clock_register(struct posix_clock *clk, dev_t devid); 1390606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 1400606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran/** 1410606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * posix_clock_unregister() - unregister a clock 1420606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * @clk: Clock instance previously registered via posix_clock_register() 1430606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * 1440606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * A clock driver calls this function to remove itself from the clock 1450606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * device subsystem. The posix_clock itself will remain (in an 1460606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * inactive state) until its reference count drops to zero, at which 1470606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran * point it will be deallocated with its 'release' method. 1480606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran */ 1490606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochranvoid posix_clock_unregister(struct posix_clock *clk); 1500606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran 1510606f422b453f76c31ab2b1bd52943ff06a2dcf2Richard Cochran#endif 152