Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[pandora-kernel.git] / drivers / char / rtc.c
index 656f8c0..c7dac9b 100644 (file)
  *     1.09a   Pete Zaitcev: Sun SPARC
  *     1.09b   Jeff Garzik: Modularize, init cleanup
  *     1.09c   Jeff Garzik: SMP cleanup
- *     1.10    Paul Barton-Davis: add support for async I/O
+ *     1.10    Paul Barton-Davis: add support for async I/O
  *     1.10a   Andrea Arcangeli: Alpha updates
  *     1.10b   Andrew Morton: SMP lock fix
  *     1.10c   Cesar Barros: SMP locking fixes and cleanup
  *     1.10d   Paul Gortmaker: delete paranoia check in rtc_exit
  *     1.10e   Maciej W. Rozycki: Handle DECstation's year weirdness.
- *      1.11    Takashi Iwai: Kernel access functions
+ *     1.11    Takashi Iwai: Kernel access functions
  *                           rtc_register/rtc_unregister/rtc_control
  *      1.11a   Daniele Bellucci: Audit create_proc_read_entry in rtc_init
  *     1.12    Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
@@ -113,9 +113,14 @@ static int rtc_has_irq = 1;
 #define hpet_set_rtc_irq_bit(arg)              0
 #define hpet_rtc_timer_init()                  do { } while (0)
 #define hpet_rtc_dropped_irq()                         0
-static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {return 0;}
+#ifdef RTC_IRQ
+static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+{
+       return 0;
+}
+#endif
 #else
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif
 
 /*
@@ -130,7 +135,9 @@ static struct fasync_struct *rtc_async_queue;
 static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
 
 #ifdef RTC_IRQ
-static struct timer_list rtc_irq_timer;
+static void rtc_dropped_irq(unsigned long data);
+
+static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
 #endif
 
 static ssize_t rtc_read(struct file *file, char __user *buf,
@@ -145,8 +152,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait);
 
 static void get_rtc_alm_time (struct rtc_time *alm_tm);
 #ifdef RTC_IRQ
-static void rtc_dropped_irq(unsigned long data);
-
 static void set_rtc_irq_bit_locked(unsigned char bit);
 static void mask_rtc_irq_bit_locked(unsigned char bit);
 
@@ -165,7 +170,9 @@ static void mask_rtc_irq_bit(unsigned char bit)
 }
 #endif
 
+#ifdef CONFIG_PROC_FS
 static int rtc_proc_open(struct inode *inode, struct file *file);
+#endif
 
 /*
  *     Bits in rtc_status. (6 bits of room for future expansion)
@@ -229,7 +236,7 @@ static inline unsigned char rtc_is_updating(void)
  *     (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
  */
 
-irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t rtc_interrupt(int irq, void *dev_id)
 {
        /*
         *      Can be an alarm interrupt, update complete interrupt,
@@ -275,7 +282,7 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  */
 static ctl_table rtc_table[] = {
        {
-               .ctl_name       = 1,
+               .ctl_name       = CTL_UNNUMBERED,
                .procname       = "max-user-freq",
                .data           = &rtc_max_user_freq,
                .maxlen         = sizeof(int),
@@ -287,9 +294,8 @@ static ctl_table rtc_table[] = {
 
 static ctl_table rtc_root[] = {
        {
-               .ctl_name       = 1,
+               .ctl_name       = CTL_UNNUMBERED,
                .procname       = "rtc",
-               .maxlen         = 0,
                .mode           = 0555,
                .child          = rtc_table,
        },
@@ -300,7 +306,6 @@ static ctl_table dev_root[] = {
        {
                .ctl_name       = CTL_DEV,
                .procname       = "dev",
-               .maxlen         = 0,
                .mode           = 0555,
                .child          = rtc_root,
        },
@@ -311,7 +316,7 @@ static struct ctl_table_header *sysctl_header;
 
 static int __init init_sysctl(void)
 {
-    sysctl_header = register_sysctl_table(dev_root, 0);
+    sysctl_header = register_sysctl_table(dev_root);
     return 0;
 }
 
@@ -447,8 +452,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
 
                spin_lock_irqsave (&rtc_lock, flags);
                if (!(rtc_status & RTC_TIMER_ON)) {
-                       rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
-                       add_timer(&rtc_irq_timer);
+                       mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq +
+                                       2*HZ/100);
                        rtc_status |= RTC_TIMER_ON;
                }
                set_rtc_irq_bit_locked(RTC_PIE);
@@ -906,6 +911,7 @@ static struct miscdevice rtc_dev = {
        .fops           = &rtc_fops,
 };
 
+#ifdef CONFIG_PROC_FS
 static const struct file_operations rtc_proc_fops = {
        .owner = THIS_MODULE,
        .open = rtc_proc_open,
@@ -913,14 +919,13 @@ static const struct file_operations rtc_proc_fops = {
        .llseek = seq_lseek,
        .release = single_release,
 };
-
-#if defined(RTC_IRQ) && !defined(__sparc__)
-static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 
 static int __init rtc_init(void)
 {
+#ifdef CONFIG_PROC_FS
        struct proc_dir_entry *ent;
+#endif
 #if defined(__alpha__) || defined(__mips__)
        unsigned int year, ctrl;
        char *guess = NULL;
@@ -932,9 +937,11 @@ static int __init rtc_init(void)
        struct sparc_isa_bridge *isa_br;
        struct sparc_isa_device *isa_dev;
 #endif
-#endif
-#ifndef __sparc__
+#else
        void *r;
+#ifdef RTC_IRQ
+       irq_handler_t rtc_int_handler_ptr;
+#endif
 #endif
 
 #ifdef __sparc__
@@ -958,6 +965,7 @@ static int __init rtc_init(void)
                }
        }
 #endif
+       rtc_has_irq = 0;
        printk(KERN_ERR "rtc_init: no PC rtc found\n");
        return -EIO;
 
@@ -972,6 +980,7 @@ found:
         * PCI Slot 2 INTA# (and some INTx# in Slot 1).
         */
        if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
+               rtc_has_irq = 0;
                printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
                return -EIO;
        }
@@ -982,6 +991,9 @@ no_irq:
        else
                r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
        if (!r) {
+#ifdef RTC_IRQ
+               rtc_has_irq = 0;
+#endif
                printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
                       (long)(RTC_PORT(0)));
                return -EIO;
@@ -996,6 +1008,7 @@ no_irq:
 
        if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
                /* Yeah right, seeing as irq 8 doesn't even hit the bus. */
+               rtc_has_irq = 0;
                printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
                if (RTC_IOMAPPED)
                        release_region(RTC_PORT(0), RTC_IO_EXTENT);
@@ -1012,21 +1025,19 @@ no_irq:
        if (misc_register(&rtc_dev)) {
 #ifdef RTC_IRQ
                free_irq(RTC_IRQ, NULL);
+               rtc_has_irq = 0;
 #endif
                release_region(RTC_PORT(0), RTC_IO_EXTENT);
                return -ENODEV;
        }
 
+#ifdef CONFIG_PROC_FS
        ent = create_proc_entry("driver/rtc", 0, NULL);
-       if (!ent) {
-#ifdef RTC_IRQ
-               free_irq(RTC_IRQ, NULL);
+       if (ent)
+               ent->proc_fops = &rtc_proc_fops;
+       else
+               printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
 #endif
-               release_region(RTC_PORT(0), RTC_IO_EXTENT);
-               misc_deregister(&rtc_dev);
-               return -ENOMEM;
-       }
-       ent->proc_fops = &rtc_proc_fops;
 
 #if defined(__alpha__) || defined(__mips__)
        rtc_freq = HZ;
@@ -1071,8 +1082,6 @@ no_irq:
        if (rtc_has_irq == 0)
                goto no_irq2;
 
-       init_timer(&rtc_irq_timer);
-       rtc_irq_timer.function = rtc_dropped_irq;
        spin_lock_irq(&rtc_lock);
        rtc_freq = 1024;
        if (!hpet_set_periodic_freq(rtc_freq)) {
@@ -1159,6 +1168,7 @@ static void rtc_dropped_irq(unsigned long data)
 }
 #endif
 
+#ifdef CONFIG_PROC_FS
 /*
  *     Info exported via "/proc/driver/rtc".
  */
@@ -1243,6 +1253,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
 {
        return single_open(file, rtc_proc_show, NULL);
 }
+#endif
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {