diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index bcc96ab7793f..670fd8a2970e 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -574,12 +574,6 @@ static const struct rtc_class_ops cmos_rtc_ops = { .alarm_irq_enable = cmos_alarm_irq_enable, }; -static const struct rtc_class_ops cmos_rtc_ops_no_alarm = { - .read_time = cmos_read_time, - .set_time = cmos_set_time, - .proc = cmos_procfs, -}; - /*----------------------------------------------------------------*/ /* @@ -649,11 +643,10 @@ static struct cmos_rtc cmos_rtc; static irqreturn_t cmos_interrupt(int irq, void *p) { - unsigned long flags; u8 irqstat; u8 rtc_control; - spin_lock_irqsave(&rtc_lock, flags); + spin_lock(&rtc_lock); /* When the HPET interrupt handler calls us, the interrupt * status is passed as arg1 instead of the irq number. But @@ -687,7 +680,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p) hpet_mask_rtc_irq_bit(RTC_AIE); CMOS_READ(RTC_INTR_FLAGS); } - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock(&rtc_lock); if (is_intr(irqstat)) { rtc_update_irq(p, 1, irqstat); @@ -805,6 +798,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) spin_lock_irq(&rtc_lock); + /* Ensure that the RTC is accessible. Bit 6 must be 0! */ + if ((CMOS_READ(RTC_VALID) & 0x40) != 0) { + spin_unlock_irq(&rtc_lock); + dev_warn(dev, "not accessible\n"); + retval = -ENXIO; + goto cleanup1; + } + if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) { /* force periodic irq to CMOS reset default of 1024Hz; * @@ -857,21 +858,22 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); goto cleanup1; } - - cmos_rtc.rtc->ops = &cmos_rtc_ops; } else { - cmos_rtc.rtc->ops = &cmos_rtc_ops_no_alarm; + clear_bit(RTC_FEATURE_ALARM, cmos_rtc.rtc->features); } - cmos_rtc.rtc->nvram_old_abi = true; - retval = rtc_register_device(cmos_rtc.rtc); + cmos_rtc.rtc->ops = &cmos_rtc_ops; + + retval = devm_rtc_register_device(cmos_rtc.rtc); if (retval) goto cleanup2; + /* Set the sync offset for the periodic 11min update correct */ + cmos_rtc.rtc->set_offset_nsec = NSEC_PER_SEC / 2; + /* export at least the first block of NVRAM */ nvmem_cfg.size = address_space - NVRAM_OFFSET; - if (rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg)) - dev_err(dev, "nvmem registration failed\n"); + devm_rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg); dev_info(dev, "%s%s, %d bytes nvram%s\n", !is_valid_irq(rtc_irq) ? "no alarms" : @@ -1006,6 +1008,7 @@ static int cmos_suspend(struct device *dev) enable_irq_wake(cmos->irq); } + memset(&cmos->saved_wkalrm, 0, sizeof(struct rtc_wkalrm)); cmos_read_alarm(dev, &cmos->saved_wkalrm); dev_dbg(dev, "suspend%s, ctrl %02x\n", @@ -1054,6 +1057,7 @@ static void cmos_check_wkalrm(struct device *dev) return; } + memset(¤t_alarm, 0, sizeof(struct rtc_wkalrm)); cmos_read_alarm(dev, ¤t_alarm); t_current_expires = rtc_tm_to_time64(¤t_alarm.time); t_saved_expires = rtc_tm_to_time64(&cmos->saved_wkalrm.time); |