aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorDerek Basehore <dbasehore@chromium.org>2013-07-03 18:07:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:08:00 -0400
commit998a06051afe6cba392eab66fa0ef1d7e7376f6c (patch)
tree99e0a0b8a7b7650782f2751d96b665156d21629f /drivers/rtc
parentae8458949a57346e17a07768fbdb626cbe993b89 (diff)
drivers/rtc/rtc-cmos.c: work around bios clearing rtc control
The bios may clear the rtc control register when resuming the system. Since the cmos interrupt handler may now be run before the rtc_cmos is resumed, this can cause the interrupt handler to ignore an alarm since the alarm bit is not set in the rtc control register. To work around this, check if the rtc_cmos is suspended and use the stored value for the rtc control register. Signed-off-by: Derek Basehore <dbasehore@chromium.org> Reviewed-by: Sameer Nanda <snanda@chromium.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Jingoo Han <jg1.han@samsung.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: John Stultz <john.stultz@linaro.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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