X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Frtc.c;fp=drivers%2Fchar%2Frtc.c;h=7cac6d05d72353da0c69c883d1806e59cc50aa8e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=ff4f09804865546527ca6926dc5c4f1ab1317605;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index ff4f09804..7cac6d05d 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -46,10 +46,10 @@ * 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.12ac Alan Cox: Allow read access to the day of week register */ -#define RTC_VERSION "1.12" +#define RTC_VERSION "1.12ac" #define RTC_IO_EXTENT 0x8 @@ -78,6 +78,7 @@ #include #include #include +#include #include #include @@ -148,8 +149,22 @@ 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(unsigned char bit); -static void mask_rtc_irq_bit(unsigned char bit); +static void set_rtc_irq_bit_locked(unsigned char bit); +static void mask_rtc_irq_bit_locked(unsigned char bit); + +static inline void set_rtc_irq_bit(unsigned char bit) +{ + spin_lock_irq(&rtc_lock); + set_rtc_irq_bit_locked(bit); + spin_unlock_irq(&rtc_lock); +} + +static void mask_rtc_irq_bit(unsigned char bit) +{ + spin_lock_irq(&rtc_lock); + mask_rtc_irq_bit_locked(bit); + spin_unlock_irq(&rtc_lock); +} #endif static int rtc_proc_open(struct inode *inode, struct file *file); @@ -400,18 +415,19 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) } case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ { - mask_rtc_irq_bit(RTC_PIE); + unsigned long flags; /* can be called from isr via rtc_control() */ + spin_lock_irqsave (&rtc_lock, flags); + mask_rtc_irq_bit_locked(RTC_PIE); if (rtc_status & RTC_TIMER_ON) { - spin_lock_irq (&rtc_lock); rtc_status &= ~RTC_TIMER_ON; del_timer(&rtc_irq_timer); - spin_unlock_irq (&rtc_lock); } + spin_unlock_irqrestore (&rtc_lock, flags); return 0; } case RTC_PIE_ON: /* Allow periodic ints */ { - + unsigned long flags; /* can be called from isr via rtc_control() */ /* * We don't really want Joe User enabling more * than 64Hz of interrupts on a multi-user machine. @@ -420,14 +436,14 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) (!capable(CAP_SYS_RESOURCE))) return -EACCES; + spin_lock_irqsave (&rtc_lock, flags); if (!(rtc_status & RTC_TIMER_ON)) { - spin_lock_irq (&rtc_lock); rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; add_timer(&rtc_irq_timer); rtc_status |= RTC_TIMER_ON; - spin_unlock_irq (&rtc_lock); } - set_rtc_irq_bit(RTC_PIE); + set_rtc_irq_bit_locked(RTC_PIE); + spin_unlock_irqrestore (&rtc_lock, flags); return 0; } case RTC_UIE_OFF: /* Mask ints from RTC updates. */ @@ -608,6 +624,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) { int tmp = 0; unsigned char val; + unsigned long flags; /* can be called from isr via rtc_control() */ /* * The max we can do is 8192Hz. @@ -630,9 +647,9 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) if (arg != (1<tm_sec = CMOS_READ(RTC_SECONDS); @@ -1248,6 +1261,9 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); rtc_tm->tm_year = CMOS_READ(RTC_YEAR); + /* Only set from 2.6.16 onwards */ + rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); + #ifdef CONFIG_MACH_DECSTATION real_year = CMOS_READ(RTC_DEC_YEAR); #endif @@ -1262,6 +1278,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) BCD_TO_BIN(rtc_tm->tm_mday); BCD_TO_BIN(rtc_tm->tm_mon); BCD_TO_BIN(rtc_tm->tm_year); + BCD_TO_BIN(rtc_tm->tm_wday); } #ifdef CONFIG_MACH_DECSTATION @@ -1312,40 +1329,32 @@ static void get_rtc_alm_time(struct rtc_time *alm_tm) * meddles with the interrupt enable/disable bits. */ -static void mask_rtc_irq_bit(unsigned char bit) +static void mask_rtc_irq_bit_locked(unsigned char bit) { unsigned char val; - spin_lock_irq(&rtc_lock); - if (hpet_mask_rtc_irq_bit(bit)) { - spin_unlock_irq(&rtc_lock); + if (hpet_mask_rtc_irq_bit(bit)) return; - } val = CMOS_READ(RTC_CONTROL); val &= ~bit; CMOS_WRITE(val, RTC_CONTROL); CMOS_READ(RTC_INTR_FLAGS); rtc_irq_data = 0; - spin_unlock_irq(&rtc_lock); } -static void set_rtc_irq_bit(unsigned char bit) +static void set_rtc_irq_bit_locked(unsigned char bit) { unsigned char val; - spin_lock_irq(&rtc_lock); - if (hpet_set_rtc_irq_bit(bit)) { - spin_unlock_irq(&rtc_lock); + if (hpet_set_rtc_irq_bit(bit)) return; - } val = CMOS_READ(RTC_CONTROL); val |= bit; CMOS_WRITE(val, RTC_CONTROL); CMOS_READ(RTC_INTR_FLAGS); rtc_irq_data = 0; - spin_unlock_irq(&rtc_lock); } #endif