diff options
author | Rob Clark <rob@ti.com> | 2010-06-01 13:36:22 -0500 |
---|---|---|
committer | Santosh Shilimkar <santosh.shilimkar@ti.com> | 2010-07-12 11:49:09 +0530 |
commit | 86b7095601dc95ea952475708d8d8f0297bd499b (patch) | |
tree | 39358bf7599bdc1447c23c1a4a970f790cdfd380 /arch/arm | |
parent | d89507031df25ffc65ab4028e735848823b1dc85 (diff) |
add timer32 driver interface for userspace
The 32ksync counter is useful to use for timestamping, and for other cases
where an aligned timestamp across the various cores on OMAP is required.
Signed-off-by: Rob Clark <rob@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/plat-omap/timer-32k-sync.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/timer-32k-sync.c b/arch/arm/plat-omap/timer-32k-sync.c index f6de66fc63c2..24a00d4cd928 100644 --- a/arch/arm/plat-omap/timer-32k-sync.c +++ b/arch/arm/plat-omap/timer-32k-sync.c @@ -112,6 +112,76 @@ void read_persistent_clock(struct timespec *ts) *ts = *tsp; } +/* ------------------------------------------------------------------------- */ +#define DEVNAME "timer32k" +#include <linux/fs.h> +#include <linux/timer-32k.h> + +static int omap_32k_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct omap_32k_sync_device *omap = thecs; + + if (!omap) + return -ENODEV; + + switch (cmd) { + case OMAP_32K_READ: { + uint32_t *t = (uint32_t *)arg; + *t = omap_32k_sync_readl(omap->base, 0x10) - omap->offset_32k; + return 0; + } + case OMAP_32K_READRAW: { + uint32_t *t = (uint32_t *)arg; + *t = omap_32k_sync_readl(omap->base, 0x10); + return 0; + } + } + + return -EINVAL; +} + +static int __init omap_32k_sync_register_chrdev(void) +{ + int major; + static struct file_operations fops = { + .ioctl = omap_32k_ioctl + }; + static struct class *cls; + struct device *dev; + + major = register_chrdev(0, DEVNAME, &fops); + + if (major <= 0) { + printk(KERN_ERR "timer-32k-sync: unable to get major number\n"); + goto exit_disable; + } + + cls = class_create(THIS_MODULE, DEVNAME); + + if (IS_ERR(cls)) { + printk(KERN_ERR "timer-32k-sync: unable to create device class\n"); + goto exit_unregister; + } + + dev = device_create(cls, NULL, MKDEV(major, 0), NULL, DEVNAME); + + if (IS_ERR(dev)) { + printk(KERN_ERR "timer-32k-sync: unable to create device\n"); + goto exit_destroy_class; + } + + return 0; + +exit_destroy_class: + class_destroy(cls); +exit_unregister: + unregister_chrdev(major, DEVNAME); +exit_disable: + return -EBUSY; +} +/* ------------------------------------------------------------------------- */ + static int __init omap_32k_sync_probe(struct platform_device *pdev) { struct omap_32k_sync_device *omap; @@ -187,6 +257,8 @@ static int __init omap_32k_sync_probe(struct platform_device *pdev) */ thecs = omap; + omap_32k_sync_register_chrdev(); + return 0; err5: |