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