summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2010-06-01 13:36:22 -0500
committerSantosh Shilimkar <santosh.shilimkar@ti.com>2010-07-12 11:49:09 +0530
commit86b7095601dc95ea952475708d8d8f0297bd499b (patch)
tree39358bf7599bdc1447c23c1a4a970f790cdfd380 /arch/arm
parentd89507031df25ffc65ab4028e735848823b1dc85 (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.c72
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: