aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-cmos.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index a6727d977330..be06d7150de5 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -556,17 +556,24 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
556 rtc_control = CMOS_READ(RTC_CONTROL); 556 rtc_control = CMOS_READ(RTC_CONTROL);
557 if (is_hpet_enabled()) 557 if (is_hpet_enabled())
558 irqstat = (unsigned long)irq & 0xF0; 558 irqstat = (unsigned long)irq & 0xF0;
559 irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; 559
560 /* If we were suspended, RTC_CONTROL may not be accurate since the
561 * bios may have cleared it.
562 */
563 if (!cmos_rtc.suspend_ctrl)
564 irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
565 else
566 irqstat &= (cmos_rtc.suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
560 567
561 /* All Linux RTC alarms should be treated as if they were oneshot. 568 /* All Linux RTC alarms should be treated as if they were oneshot.
562 * Similar code may be needed in system wakeup paths, in case the 569 * Similar code may be needed in system wakeup paths, in case the
563 * alarm woke the system. 570 * alarm woke the system.
564 */ 571 */
565 if (irqstat & RTC_AIE) { 572 if (irqstat & RTC_AIE) {
573 cmos_rtc.suspend_ctrl &= ~RTC_AIE;
566 rtc_control &= ~RTC_AIE; 574 rtc_control &= ~RTC_AIE;
567 CMOS_WRITE(rtc_control, RTC_CONTROL); 575 CMOS_WRITE(rtc_control, RTC_CONTROL);
568 hpet_mask_rtc_irq_bit(RTC_AIE); 576 hpet_mask_rtc_irq_bit(RTC_AIE);
569
570 CMOS_READ(RTC_INTR_FLAGS); 577 CMOS_READ(RTC_INTR_FLAGS);
571 } 578 }
572 spin_unlock(&rtc_lock); 579 spin_unlock(&rtc_lock);
@@ -839,21 +846,23 @@ static inline int cmos_poweroff(struct device *dev)
839static int cmos_resume(struct device *dev) 846static int cmos_resume(struct device *dev)
840{ 847{
841 struct cmos_rtc *cmos = dev_get_drvdata(dev); 848 struct cmos_rtc *cmos = dev_get_drvdata(dev);
842 unsigned char tmp = cmos->suspend_ctrl; 849 unsigned char tmp;
850
851 if (cmos->enabled_wake) {
852 if (cmos->wake_off)
853 cmos->wake_off(dev);
854 else
855 disable_irq_wake(cmos->irq);
856 cmos->enabled_wake = 0;
857 }
843 858
859 spin_lock_irq(&rtc_lock);
860 tmp = cmos->suspend_ctrl;
861 cmos->suspend_ctrl = 0;
844 /* re-enable any irqs previously active */ 862 /* re-enable any irqs previously active */
845 if (tmp & RTC_IRQMASK) { 863 if (tmp & RTC_IRQMASK) {
846 unsigned char mask; 864 unsigned char mask;
847 865
848 if (cmos->enabled_wake) {
849 if (cmos->wake_off)
850 cmos->wake_off(dev);
851 else
852 disable_irq_wake(cmos->irq);
853 cmos->enabled_wake = 0;
854 }
855
856 spin_lock_irq(&rtc_lock);
857 if (device_may_wakeup(dev)) 866 if (device_may_wakeup(dev))
858 hpet_rtc_timer_init(); 867 hpet_rtc_timer_init();
859 868
@@ -873,8 +882,8 @@ static int cmos_resume(struct device *dev)
873 tmp &= ~RTC_AIE; 882 tmp &= ~RTC_AIE;
874 hpet_mask_rtc_irq_bit(RTC_AIE); 883 hpet_mask_rtc_irq_bit(RTC_AIE);
875 } while (mask & RTC_AIE); 884 } while (mask & RTC_AIE);
876 spin_unlock_irq(&rtc_lock);
877 } 885 }
886 spin_unlock_irq(&rtc_lock);
878 887
879 dev_dbg(dev, "resume, ctrl %02x\n", tmp); 888 dev_dbg(dev, "resume, ctrl %02x\n", tmp);
880 889