Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[firefly-linux-kernel-4.4.55.git] / drivers / rtc / rtc-cmos.c
index f1cb706445c739d7eee047a06482e63f0444de83..be06d7150de5d4b81f6c84e9c5cc874e26360e70 100644 (file)
@@ -326,7 +326,7 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
 static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
-       unsigned char   mon, mday, hrs, min, sec, rtc_control;
+       unsigned char mon, mday, hrs, min, sec, rtc_control;
 
        if (!is_valid_irq(cmos->irq))
                return -EIO;
@@ -556,17 +556,24 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
        rtc_control = CMOS_READ(RTC_CONTROL);
        if (is_hpet_enabled())
                irqstat = (unsigned long)irq & 0xF0;
-       irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+
+       /* If we were suspended, RTC_CONTROL may not be accurate since the
+        * bios may have cleared it.
+        */
+       if (!cmos_rtc.suspend_ctrl)
+               irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+       else
+               irqstat &= (cmos_rtc.suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
 
        /* All Linux RTC alarms should be treated as if they were oneshot.
         * Similar code may be needed in system wakeup paths, in case the
         * alarm woke the system.
         */
        if (irqstat & RTC_AIE) {
+               cmos_rtc.suspend_ctrl &= ~RTC_AIE;
                rtc_control &= ~RTC_AIE;
                CMOS_WRITE(rtc_control, RTC_CONTROL);
                hpet_mask_rtc_irq_bit(RTC_AIE);
-
                CMOS_READ(RTC_INTR_FLAGS);
        }
        spin_unlock(&rtc_lock);
@@ -691,7 +698,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
        /* FIXME:
         * <asm-generic/rtc.h> doesn't know 12-hour mode either.
         */
-       if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) {
+       if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) {
                dev_warn(dev, "only 24-hr supported\n");
                retval = -ENXIO;
                goto cleanup1;
@@ -839,21 +846,23 @@ static inline int cmos_poweroff(struct device *dev)
 static int cmos_resume(struct device *dev)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
-       unsigned char   tmp = cmos->suspend_ctrl;
+       unsigned char tmp;
+
+       if (cmos->enabled_wake) {
+               if (cmos->wake_off)
+                       cmos->wake_off(dev);
+               else
+                       disable_irq_wake(cmos->irq);
+               cmos->enabled_wake = 0;
+       }
 
+       spin_lock_irq(&rtc_lock);
+       tmp = cmos->suspend_ctrl;
+       cmos->suspend_ctrl = 0;
        /* re-enable any irqs previously active */
        if (tmp & RTC_IRQMASK) {
                unsigned char   mask;
 
-               if (cmos->enabled_wake) {
-                       if (cmos->wake_off)
-                               cmos->wake_off(dev);
-                       else
-                               disable_irq_wake(cmos->irq);
-                       cmos->enabled_wake = 0;
-               }
-
-               spin_lock_irq(&rtc_lock);
                if (device_may_wakeup(dev))
                        hpet_rtc_timer_init();
 
@@ -873,8 +882,8 @@ static int cmos_resume(struct device *dev)
                        tmp &= ~RTC_AIE;
                        hpet_mask_rtc_irq_bit(RTC_AIE);
                } while (mask & RTC_AIE);
-               spin_unlock_irq(&rtc_lock);
        }
+       spin_unlock_irq(&rtc_lock);
 
        dev_dbg(dev, "resume, ctrl %02x\n", tmp);
 
@@ -991,7 +1000,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        cmos_wake_setup(&pnp->dev);
 
-       if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
+       if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0))
                /* Some machines contain a PNP entry for the RTC, but
                 * don't define the IRQ. It should always be safe to
                 * hardcode it in these cases