diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f1cb706445c7..be06d7150de5 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -326,7 +326,7 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) | |||
326 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 326 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
327 | { | 327 | { |
328 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 328 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
329 | unsigned char mon, mday, hrs, min, sec, rtc_control; | 329 | unsigned char mon, mday, hrs, min, sec, rtc_control; |
330 | 330 | ||
331 | if (!is_valid_irq(cmos->irq)) | 331 | if (!is_valid_irq(cmos->irq)) |
332 | return -EIO; | 332 | return -EIO; |
@@ -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); |
@@ -691,7 +698,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
691 | /* FIXME: | 698 | /* FIXME: |
692 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 699 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
693 | */ | 700 | */ |
694 | if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) { | 701 | if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) { |
695 | dev_warn(dev, "only 24-hr supported\n"); | 702 | dev_warn(dev, "only 24-hr supported\n"); |
696 | retval = -ENXIO; | 703 | retval = -ENXIO; |
697 | goto cleanup1; | 704 | goto cleanup1; |
@@ -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 | ||
@@ -991,7 +1000,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
991 | { | 1000 | { |
992 | cmos_wake_setup(&pnp->dev); | 1001 | cmos_wake_setup(&pnp->dev); |
993 | 1002 | ||
994 | if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) | 1003 | if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) |
995 | /* Some machines contain a PNP entry for the RTC, but | 1004 | /* Some machines contain a PNP entry for the RTC, but |
996 | * don't define the IRQ. It should always be safe to | 1005 | * don't define the IRQ. It should always be safe to |
997 | * hardcode it in these cases | 1006 | * hardcode it in these cases |