diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/rtc/class.c | 14 | ||||
-rw-r--r-- | drivers/rtc/interface.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 19 | ||||
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 50 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf8583.c | 29 | ||||
-rw-r--r-- | drivers/rtc/rtc-sa1100.c | 12 |
7 files changed, 86 insertions, 51 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4bbca500d3d..95826b92ca4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -101,7 +101,7 @@ comment "RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS' real time clock" - depends on RTC_CLASS && (X86_PC || ALPHA || ARM26 || ARM \ + depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ || M32R || ATARI || POWERPC) help Say "yes" here to get direct support for the real time clock @@ -207,10 +207,12 @@ config RTC_DRV_PCF8563 config RTC_DRV_PCF8583 tristate "Philips PCF8583" - depends on RTC_CLASS && I2C + depends on RTC_CLASS && I2C && ARCH_RPC help - If you say yes here you get support for the - Philips PCF8583 RTC chip. + If you say yes here you get support for the Philips PCF8583 + RTC chip found on Acorn RiscPCs. This driver supports the + platform specific method of retrieving the current year from + the RTC's SRAM. This driver can also be built as a module. If so, the module will be called rtc-pcf8583. diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 7a0d8ee2de9..04aaa634723 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -113,10 +113,16 @@ EXPORT_SYMBOL_GPL(rtc_device_register); */ void rtc_device_unregister(struct rtc_device *rtc) { - mutex_lock(&rtc->ops_lock); - rtc->ops = NULL; - mutex_unlock(&rtc->ops_lock); - class_device_unregister(&rtc->class_dev); + if (class_device_get(&rtc->class_dev) != NULL) { + mutex_lock(&rtc->ops_lock); + /* remove innards of this RTC, then disable it, before + * letting any rtc_class_open() users access it again + */ + class_device_unregister(&rtc->class_dev); + rtc->ops = NULL; + mutex_unlock(&rtc->ops_lock); + class_device_put(&rtc->class_dev); + } } EXPORT_SYMBOL_GPL(rtc_device_unregister); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 6f11f6dfdd9..ef40df0f169 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -179,7 +179,7 @@ struct class_device *rtc_class_open(char *name) down(&rtc_class->sem); list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { - class_dev = class_dev_tmp; + class_dev = class_device_get(class_dev_tmp); break; } } @@ -197,6 +197,7 @@ EXPORT_SYMBOL_GPL(rtc_class_open); void rtc_class_close(struct class_device *class_dev) { module_put(to_rtc_device(class_dev)->owner); + class_device_put(class_dev); } EXPORT_SYMBOL_GPL(rtc_class_close); diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index a724ab49a79..ac0e68e2f02 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -164,6 +164,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) tm.tm_min = alrm->time.tm_min; tm.tm_sec = alrm->time.tm_sec; + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); at91_sys_write(AT91_RTC_TIMALR, BIN2BCD(tm.tm_sec) << 0 | BIN2BCD(tm.tm_min) << 8 @@ -174,6 +175,9 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | BIN2BCD(tm.tm_mday) << 24 | AT91_RTC_DATEEN | AT91_RTC_MTHEN); + if (alrm->enabled) + at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); @@ -303,6 +307,12 @@ static int __init at91_rtc_probe(struct platform_device *pdev) return ret; } + /* cpu init code should really have flagged this device as + * being wake-capable; if it didn't, do that here. + */ + if (!device_can_wakeup(&pdev->dev)) + device_init_wakeup(&pdev->dev, 1); + rtc = rtc_device_register(pdev->name, &pdev->dev, &at91_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { @@ -310,7 +320,6 @@ static int __init at91_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc); } platform_set_drvdata(pdev, rtc); - device_init_wakeup(&pdev->dev, 1); printk(KERN_INFO "AT91 Real Time Clock driver.\n"); return 0; @@ -319,7 +328,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) /* * Disable and remove the RTC driver */ -static int __devexit at91_rtc_remove(struct platform_device *pdev) +static int __exit at91_rtc_remove(struct platform_device *pdev) { struct rtc_device *rtc = platform_get_drvdata(pdev); @@ -331,7 +340,6 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev) rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); - device_init_wakeup(&pdev->dev, 0); return 0; } @@ -404,8 +412,7 @@ static int at91_rtc_resume(struct platform_device *pdev) #endif static struct platform_driver at91_rtc_driver = { - .probe = at91_rtc_probe, - .remove = at91_rtc_remove, + .remove = __exit_p(at91_rtc_remove), .suspend = at91_rtc_suspend, .resume = at91_rtc_resume, .driver = { @@ -416,7 +423,7 @@ static struct platform_driver at91_rtc_driver = { static int __init at91_rtc_init(void) { - return platform_driver_register(&at91_rtc_driver); + return platform_driver_probe(&at91_rtc_driver, at91_rtc_probe); } static void __exit at91_rtc_exit(void) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 85bf795abdc..7c0d6091007 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -59,6 +59,19 @@ struct cmos_rtc { static const char driver_name[] = "rtc_cmos"; +/* The RTC_INTR register may have e.g. RTC_PF set even if RTC_PIE is clear; + * always mask it against the irq enable bits in RTC_CONTROL. Bit values + * are the same: PF==PIE, AF=AIE, UF=UIE; so RTC_IRQMASK works with both. + */ +#define RTC_IRQMASK (RTC_PF | RTC_AF | RTC_UF) + +static inline int is_intr(u8 rtc_intr) +{ + if (!(rtc_intr & RTC_IRQF)) + return 0; + return rtc_intr & RTC_IRQMASK; +} + /*----------------------------------------------------------------*/ static int cmos_read_time(struct device *dev, struct rtc_time *t) @@ -188,7 +201,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) rtc_control &= ~RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (rtc_intr) + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(rtc_intr)) rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); /* update alarm */ @@ -207,7 +221,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) rtc_control |= RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (rtc_intr) + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(rtc_intr)) rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); } @@ -287,7 +302,8 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) } CMOS_WRITE(rtc_control, RTC_CONTROL); rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (rtc_intr) + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(rtc_intr)) rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); spin_unlock_irqrestore(&rtc_lock, flags); return 0; @@ -353,12 +369,10 @@ static irqreturn_t cmos_interrupt(int irq, void *p) spin_lock(&rtc_lock); irqstat = CMOS_READ(RTC_INTR_FLAGS); + irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF; spin_unlock(&rtc_lock); - if (irqstat) { - /* NOTE: irqstat may have e.g. RTC_PF set - * even when RTC_PIE is clear... - */ + if (is_intr(irqstat)) { rtc_update_irq(p, 1, irqstat); return IRQ_HANDLED; } else @@ -525,25 +539,26 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) { struct cmos_rtc *cmos = dev_get_drvdata(dev); int do_wake = device_may_wakeup(dev); - unsigned char tmp, irqstat; + unsigned char tmp; /* only the alarm might be a wakeup event source */ spin_lock_irq(&rtc_lock); cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { + unsigned char irqstat; + if (do_wake) tmp &= ~(RTC_PIE|RTC_UIE); else tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE); CMOS_WRITE(tmp, RTC_CONTROL); irqstat = CMOS_READ(RTC_INTR_FLAGS); - } else - irqstat = 0; + irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(irqstat)) + rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat); + } spin_unlock_irq(&rtc_lock); - if (irqstat) - rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat); - /* ACPI HOOK: enable ACPI_EVENT_RTC when (tmp & RTC_AIE) * ... it'd be best if we could do that under rtc_lock. */ @@ -573,9 +588,10 @@ static int cmos_resume(struct device *dev) spin_lock_irq(&rtc_lock); CMOS_WRITE(tmp, RTC_CONTROL); tmp = CMOS_READ(RTC_INTR_FLAGS); - spin_unlock_irq(&rtc_lock); - if (tmp) + tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(tmp)) rtc_update_irq(&cmos->rtc->class_dev, 1, tmp); + spin_unlock_irq(&rtc_lock); } pr_debug("%s: resume, ctrl %02x\n", @@ -594,7 +610,7 @@ static int cmos_resume(struct device *dev) /*----------------------------------------------------------------*/ /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, - * the device node may alternatively be created as a PNP device. + * the device node will always be created as a PNPACPI device. */ #ifdef CONFIG_PNPACPI @@ -673,7 +689,7 @@ module_exit(cmos_exit); /*----------------------------------------------------------------*/ /* Platform setup should have set up an RTC device, when PNPACPI is - * unavailable ... this is the normal case, common even on PCs. + * unavailable ... this could happen even on (older) PCs. */ static int __init cmos_platform_probe(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 5875ebb8c79..d48b0337458 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -40,7 +40,7 @@ struct pcf8583 { #define CTRL_ALARM 0x02 #define CTRL_TIMER 0x01 -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; /* Module parameters */ I2C_CLIENT_INSMOD; @@ -81,11 +81,11 @@ static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt) buf[4] &= 0x3f; buf[5] &= 0x1f; - dt->tm_sec = BCD_TO_BIN(buf[1]); - dt->tm_min = BCD_TO_BIN(buf[2]); - dt->tm_hour = BCD_TO_BIN(buf[3]); - dt->tm_mday = BCD_TO_BIN(buf[4]); - dt->tm_mon = BCD_TO_BIN(buf[5]); + dt->tm_sec = BCD2BIN(buf[1]); + dt->tm_min = BCD2BIN(buf[2]); + dt->tm_hour = BCD2BIN(buf[3]); + dt->tm_mday = BCD2BIN(buf[4]); + dt->tm_mon = BCD2BIN(buf[5]) - 1; } return ret == 2 ? 0 : -EIO; @@ -99,14 +99,14 @@ static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, buf[0] = 0; buf[1] = get_ctrl(client) | 0x80; buf[2] = 0; - buf[3] = BIN_TO_BCD(dt->tm_sec); - buf[4] = BIN_TO_BCD(dt->tm_min); - buf[5] = BIN_TO_BCD(dt->tm_hour); + buf[3] = BIN2BCD(dt->tm_sec); + buf[4] = BIN2BCD(dt->tm_min); + buf[5] = BIN2BCD(dt->tm_hour); if (datetoo) { len = 8; - buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6); - buf[7] = BIN_TO_BCD(dt->tm_mon) | (dt->tm_wday << 5); + buf[6] = BIN2BCD(dt->tm_mday) | (dt->tm_year << 6); + buf[7] = BIN2BCD(dt->tm_mon + 1) | (dt->tm_wday << 5); } ret = i2c_master_send(client, (char *)buf, len); @@ -226,7 +226,7 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) */ year_offset += 4; - tm->tm_year = real_year + year_offset + year[1] * 100; + tm->tm_year = (real_year + year_offset + year[1] * 100) - 1900; return 0; } @@ -237,6 +237,7 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char year[2], chk; struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year }; struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + unsigned int proper_year = tm->tm_year + 1900; int ret; /* @@ -258,8 +259,8 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) chk -= year[1] + year[0]; - year[1] = tm->tm_year / 100; - year[0] = tm->tm_year % 100; + year[1] = proper_year / 100; + year[0] = proper_year % 100; chk += year[1] + year[0]; diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 9c8ead43a59..677bae820dc 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -263,8 +263,12 @@ static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { + u32 rtsr; + memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); - alrm->pending = RTSR & RTSR_AL ? 1 : 0; + rtsr = RTSR; + alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; + alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; return 0; } @@ -275,12 +279,10 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) spin_lock_irq(&sa1100_rtc_lock); ret = rtc_update_alarm(&alrm->time); if (ret == 0) { - memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time)); - if (alrm->enabled) - enable_irq_wake(IRQ_RTCAlrm); + RTSR |= RTSR_ALE; else - disable_irq_wake(IRQ_RTCAlrm); + RTSR &= ~RTSR_ALE; } spin_unlock_irq(&sa1100_rtc_lock); |