diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 35 |
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) | |||
839 | static int cmos_resume(struct device *dev) | 846 | static 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 | ||