Merge git://git.kernel.org/pub/scm/linux/kernel/git/bunk/trivial
[pandora-kernel.git] / drivers / char / rtc.c
index cc7bd1a..66a7385 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
  *             CONFIG_HPET_EMULATE_RTC
+ *     1.12a   Maciej W. Rozycki: Handle memory-mapped chips properly.
  *     1.12ac  Alan Cox: Allow read access to the day of week register
  */
 
 #define RTC_VERSION            "1.12ac"
 
-#define RTC_IO_EXTENT  0x8
-
 /*
  *     Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
  *     interrupts disabled. Due to the index-port/data-port (0x70/0x71)
@@ -114,9 +113,9 @@ 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;}
+static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
 #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
 
 /*
@@ -210,11 +209,12 @@ static const unsigned char days_in_mo[] =
  */
 static inline unsigned char rtc_is_updating(void)
 {
+       unsigned long flags;
        unsigned char uip;
 
-       spin_lock_irq(&rtc_lock);
+       spin_lock_irqsave(&rtc_lock, flags);
        uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
-       spin_unlock_irq(&rtc_lock);
+       spin_unlock_irqrestore(&rtc_lock, flags);
        return uip;
 }
 
@@ -229,7 +229,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,
@@ -337,7 +337,15 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
        if (rtc_has_irq == 0)
                return -EIO;
 
-       if (count < sizeof(unsigned))
+       /*
+        * Historically this function used to assume that sizeof(unsigned long)
+        * is the same in userspace and kernelspace.  This lead to problems
+        * for configurations with multiple ABIs such a the MIPS o32 and 64
+        * ABIs supported on the same kernel.  So now we support read of both
+        * 4 and 8 bytes and assume that's the sizeof(unsigned long) in the
+        * userspace ABI.
+        */
+       if (count != sizeof(unsigned int) && count !=  sizeof(unsigned long))
                return -EINVAL;
 
        add_wait_queue(&rtc_wait, &wait);
@@ -368,10 +376,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
                schedule();
        } while (1);
 
-       if (count < sizeof(unsigned long))
-               retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); 
+       if (count == sizeof(unsigned int))
+               retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int);
        else
                retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long);
+       if (!retval)
+               retval = count;
  out:
        current->state = TASK_RUNNING;
        remove_wait_queue(&rtc_wait, &wait);
@@ -905,7 +915,7 @@ static const struct file_operations rtc_proc_fops = {
 };
 
 #if defined(RTC_IRQ) && !defined(__sparc__)
-static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs);
+static irq_handler_t rtc_int_handler_ptr;
 #endif
 
 static int __init rtc_init(void)
@@ -923,6 +933,9 @@ static int __init rtc_init(void)
        struct sparc_isa_device *isa_dev;
 #endif
 #endif
+#ifndef __sparc__
+       void *r;
+#endif
 
 #ifdef __sparc__
        for_each_ebus(ebus) {
@@ -964,8 +977,13 @@ found:
        }
 no_irq:
 #else
-       if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) {
-               printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0));
+       if (RTC_IOMAPPED)
+               r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
+       else
+               r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
+       if (!r) {
+               printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
+                      (long)(RTC_PORT(0)));
                return -EIO;
        }
 
@@ -979,7 +997,10 @@ 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. */
                printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
-               release_region(RTC_PORT(0), RTC_IO_EXTENT);
+               if (RTC_IOMAPPED)
+                       release_region(RTC_PORT(0), RTC_IO_EXTENT);
+               else
+                       release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
                return -EIO;
        }
        hpet_rtc_timer_init();
@@ -1079,7 +1100,10 @@ static void __exit rtc_exit (void)
        if (rtc_has_irq)
                free_irq (rtc_irq, &rtc_port);
 #else
-       release_region (RTC_PORT (0), RTC_IO_EXTENT);
+       if (RTC_IOMAPPED)
+               release_region(RTC_PORT(0), RTC_IO_EXTENT);
+       else
+               release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
 #ifdef RTC_IRQ
        if (rtc_has_irq)
                free_irq (RTC_IRQ, NULL);
@@ -1222,7 +1246,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
-       unsigned long uip_watchdog = jiffies;
+       unsigned long uip_watchdog = jiffies, flags;
        unsigned char ctrl;
 #ifdef CONFIG_MACH_DECSTATION
        unsigned int real_year;
@@ -1238,10 +1262,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
         * Once the read clears, read the RTC time (again via ioctl). Easy.
         */
 
-       while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
-               barrier();
+       while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100)
                cpu_relax();
-       }
 
        /*
         * Only the values that we read from the RTC are set. We leave
@@ -1249,7 +1271,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
         * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is
         * only updated by the RTC when initially set to a non-zero value.
         */
-       spin_lock_irq(&rtc_lock);
+       spin_lock_irqsave(&rtc_lock, flags);
        rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
        rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
        rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
@@ -1263,7 +1285,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
        real_year = CMOS_READ(RTC_DEC_YEAR);
 #endif
        ctrl = CMOS_READ(RTC_CONTROL);
-       spin_unlock_irq(&rtc_lock);
+       spin_unlock_irqrestore(&rtc_lock, flags);
 
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
        {