diff options
Diffstat (limited to 'drivers/rtc')
64 files changed, 1803 insertions, 1103 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3e84315c6f12..e215f50794b6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -5,6 +5,10 @@ config RTC_LIB bool +config RTC_MC146818_LIB + bool + select RTC_LIB + menuconfig RTC_CLASS bool "Real Time Clock" default n @@ -573,29 +577,11 @@ config RTC_DRV_EM3027 This driver can also be built as a module. If so, the module will be called rtc-em3027. -config RTC_DRV_RV3029C2 - tristate "Micro Crystal RV3029" - help - If you say yes here you get support for the Micro Crystal - RV3029 RTC chips. - - This driver can also be built as a module. If so, the module - will be called rtc-rv3029c2. - -config RTC_DRV_RV3029_HWMON - bool "HWMON support for RV3029" - depends on RTC_DRV_RV3029C2 && HWMON - depends on !(RTC_DRV_RV3029C2=y && HWMON=m) - default y - help - Say Y here if you want to expose temperature sensor data on - rtc-rv3029. - config RTC_DRV_RV8803 - tristate "Micro Crystal RV8803" + tristate "Micro Crystal RV8803, Epson RX8900" help - If you say yes here you get support for the Micro Crystal - RV8803 RTC chips. + If you say yes here you get support for the Micro Crystal RV8803 and + Epson RX8900 RTC chips. This driver can also be built as a module. If so, the module will be called rtc-rv8803. @@ -634,6 +620,15 @@ config RTC_DRV_M41T94 This driver can also be built as a module. If so, the module will be called rtc-m41t94. +config RTC_DRV_DS1302 + tristate "Dallas/Maxim DS1302" + depends on SPI + help + If you say yes here you get support for the Dallas DS1302 RTC chips. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1302. + config RTC_DRV_DS1305 tristate "Dallas/Maxim DS1305/DS1306" help @@ -679,6 +674,18 @@ config RTC_DRV_DS1390 This driver can also be built as a module. If so, the module will be called rtc-ds1390. +config RTC_DRV_MAX6916 + tristate "Maxim MAX6916" + help + If you say yes here you will get support for the + Maxim MAX6916 SPI RTC chip. + + This driver only supports the RTC feature, and not other chip + features such as alarms. + + This driver can also be built as a module. If so, the module + will be called rtc-max6916. + config RTC_DRV_R9701 tristate "Epson RTC-9701JE" help @@ -777,6 +784,25 @@ config RTC_DRV_PCF2127 This driver can also be built as a module. If so, the module will be called rtc-pcf2127. +config RTC_DRV_RV3029C2 + tristate "Micro Crystal RV3029/3049" + depends on RTC_I2C_AND_SPI + help + If you say yes here you get support for the Micro Crystal + RV3029 and RV3049 RTC chips. + + This driver can also be built as a module. If so, the module + will be called rtc-rv3029c2. + +config RTC_DRV_RV3029_HWMON + bool "HWMON support for RV3029/3049" + depends on RTC_DRV_RV3029C2 && HWMON + depends on !(RTC_DRV_RV3029C2=y && HWMON=m) + default y + help + Say Y here if you want to expose temperature sensor data on + rtc-rv3029. + comment "Platform RTC drivers" # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> @@ -785,8 +811,9 @@ comment "Platform RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS'" - depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 + depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300 default y if X86 + select RTC_MC146818_LIB help Say "yes" here to get direct support for the real time clock found in every PC or ACPI-based system, and some other boards. @@ -805,6 +832,7 @@ config RTC_DRV_CMOS config RTC_DRV_ALPHA bool "Alpha PC-style CMOS" depends on ALPHA + select RTC_MC146818_LIB default y help Direct support for the real-time clock found on every Alpha @@ -834,12 +862,6 @@ config RTC_DRV_DS1286 help If you say yes here you get support for the Dallas DS1286 RTC chips. -config RTC_DRV_DS1302 - tristate "Dallas DS1302" - depends on SH_SECUREEDGE5410 - help - If you say yes here you get support for the Dallas DS1302 RTC chips. - config RTC_DRV_DS1511 tristate "Dallas DS1511" depends on HAS_IOMEM diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ea2833723fa9..7cf7ad559c79 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_RTC_LIB) += rtc-lib.o obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o obj-$(CONFIG_RTC_SYSTOHC) += systohc.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o +obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o rtc-core-y := class.o interface.o ifdef CONFIG_RTC_DRV_EFI @@ -85,6 +86,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o +obj-$(CONFIG_RTC_DRV_MAX6916) += rtc-max6916.o obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 9ef5f6f89f98..84a52db9b05f 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -104,7 +104,17 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al else if (!rtc->ops->read_alarm) err = -EINVAL; else { - memset(alarm, 0, sizeof(struct rtc_wkalrm)); + alarm->enabled = 0; + alarm->pending = 0; + alarm->time.tm_sec = -1; + alarm->time.tm_min = -1; + alarm->time.tm_hour = -1; + alarm->time.tm_mday = -1; + alarm->time.tm_mon = -1; + alarm->time.tm_year = -1; + alarm->time.tm_wday = -1; + alarm->time.tm_yday = -1; + alarm->time.tm_isdst = -1; err = rtc->ops->read_alarm(rtc->dev.parent, alarm); } @@ -383,7 +393,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); rtc->aie_timer.period = ktime_set(0, 0); - /* Alarm has to be enabled & in the futrure for us to enqueue it */ + /* Alarm has to be enabled & in the future for us to enqueue it */ if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 < rtc->aie_timer.node.expires.tv64)) { @@ -395,8 +405,6 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_initialize_alarm); - - int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) { int err = mutex_lock_interruptible(&rtc->ops_lock); @@ -748,9 +756,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); */ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) { + struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); + struct rtc_time tm; + ktime_t now; + timer->enabled = 1; + __rtc_read_time(rtc, &tm); + now = rtc_tm_to_ktime(tm); + + /* Skip over expired timers */ + while (next) { + if (next->expires.tv64 >= now.tv64) + break; + next = timerqueue_iterate_next(next); + } + timerqueue_add(&rtc->timerqueue, &timer->node); - if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { + if (!next) { struct rtc_wkalrm alarm; int err; alarm.time = rtc_ktime_to_tm(timer->node.expires); diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index ba0d61934d35..fea9a60b06cf 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -643,17 +643,15 @@ static int abx80x_probe(struct i2c_client *client, return err; } - err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group, - &client->dev); - if (err) { - rtc_calib_remove_sysfs_group(&client->dev); + err = devm_add_action_or_reset(&client->dev, + rtc_calib_remove_sysfs_group, + &client->dev); + if (err) dev_err(&client->dev, "Failed to add sysfs cleanup action: %d\n", err); - return err; - } - return 0; + return err; } static int abx80x_remove(struct i2c_client *client) diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index 355fdb97a006..5219916ce11d 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -343,7 +343,6 @@ static struct platform_driver asm9260_rtc_driver = { .remove = asm9260_rtc_remove, .driver = { .name = "asm9260-rtc", - .owner = THIS_MODULE, .of_match_table = asm9260_dt_ids, }, }; diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 7206e2fa4383..7418a763ce52 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -268,7 +268,7 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int at91_rtc_proc(struct device *dev, struct seq_file *seq) { struct sam9_rtc *rtc = dev_get_drvdata(dev); - u32 mr = mr = rtt_readl(rtc, MR); + u32 mr = rtt_readl(rtc, MR); seq_printf(seq, "update_IRQ\t: %s\n", (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no"); @@ -375,6 +375,7 @@ static int at91_rtc_probe(struct platform_device *pdev) if (!rtc) return -ENOMEM; + spin_lock_init(&rtc->lock); rtc->irq = irq; /* platform setup code should have handled this; sigh */ diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 84fb541038be..43745cac0141 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -43,7 +43,7 @@ #include <linux/of_platform.h> /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ -#include <asm-generic/rtc.h> +#include <linux/mc146818rtc.h> struct cmos_rtc { struct rtc_device *rtc; @@ -190,10 +190,10 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr) static int cmos_read_time(struct device *dev, struct rtc_time *t) { /* REVISIT: if the clock has a "century" register, use - * that instead of the heuristic in get_rtc_time(). + * that instead of the heuristic in mc146818_get_time(). * That'll make Y3K compatility (year > 2070) easy! */ - get_rtc_time(t); + mc146818_get_time(t); return 0; } @@ -205,7 +205,7 @@ static int cmos_set_time(struct device *dev, struct rtc_time *t) * takes effect exactly 500ms after we write the register. * (Also queueing and other delays before we get this far.) */ - return set_rtc_time(t); + return mc146818_set_time(t); } static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) @@ -220,8 +220,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) * Some also support day and month, for alarms up to a year in * the future. */ - t->time.tm_mday = -1; - t->time.tm_mon = -1; spin_lock_irq(&rtc_lock); t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM); @@ -272,7 +270,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) } } } - t->time.tm_year = -1; t->enabled = !!(rtc_control & RTC_AIE); t->pending = 0; @@ -401,7 +398,7 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) return 0; } -#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) +#if IS_ENABLED(CONFIG_RTC_INTF_PROC) static int cmos_procfs(struct device *dev, struct seq_file *seq) { @@ -630,7 +627,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) address_space = 64; #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ || defined(__sparc__) || defined(__mips__) \ - || defined(__powerpc__) + || defined(__powerpc__) || defined(CONFIG_MN10300) address_space = 128; #else #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. @@ -1142,14 +1139,14 @@ static __init void cmos_of_init(struct platform_device *pdev) if (val) CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); - get_rtc_time(&time); + cmos_read_time(&pdev->dev, &time); ret = rtc_valid_tm(&time); if (ret) { struct rtc_time def_time = { .tm_year = 1, .tm_mday = 1, }; - set_rtc_time(&def_time); + cmos_set_time(&pdev->dev, &def_time); } } #else diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 1ba4371cbc2d..4273377562ec 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -85,6 +85,7 @@ static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY; rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR; rtc_tm->tm_min = v[0][0] & DA9052_RTC_MIN; + rtc_tm->tm_sec = 0; ret = rtc_valid_tm(rtc_tm); return ret; @@ -302,6 +303,13 @@ static int da9052_rtc_probe(struct platform_device *pdev) if (ret != 0) rtc_err(rtc, "Failed to disable TICKS: %d\n", ret); + device_init_wakeup(&pdev->dev, true); + rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &da9052_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc->rtc)) + return PTR_ERR(rtc->rtc); + ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", da9052_rtc_irq, rtc); if (ret != 0) { @@ -309,11 +317,7 @@ static int da9052_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(&pdev->dev, true); - - rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &da9052_rtc_ops, THIS_MODULE); - return PTR_ERR_OR_ZERO(rtc->rtc); + return 0; } static struct platform_driver da9052_rtc_driver = { diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 7ec0872d5e3b..678af8648c45 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c @@ -74,6 +74,7 @@ static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY; rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR; rtc_tm->tm_min = v[0] & DA9055_RTC_ALM_MIN; + rtc_tm->tm_sec = 0; return rtc_valid_tm(rtc_tm); } diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index c5432bf64e1c..dba60c1dfce2 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -388,6 +388,8 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) u8 day0, day1; unsigned long flags; + alm->time.tm_sec = 0; + spin_lock_irqsave(&davinci_rtc_lock, flags); davinci_rtcss_calendar_wait(davinci_rtc); diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c index 12dbd70859ae..9c82b1da2d45 100644 --- a/drivers/rtc/rtc-ds1216.c +++ b/drivers/rtc/rtc-ds1216.c @@ -11,8 +11,6 @@ #include <linux/bcd.h> #include <linux/slab.h> -#define DRV_VERSION "0.2" - struct ds1216_regs { u8 tsec; u8 sec; @@ -176,5 +174,4 @@ module_platform_driver_probe(ds1216_rtc_platform_driver, ds1216_rtc_probe); MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); MODULE_DESCRIPTION("DS1216 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-ds1216"); diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 8247a29a4eb4..ef75c349dff9 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -16,12 +16,10 @@ #include <linux/rtc.h> #include <linux/platform_device.h> #include <linux/bcd.h> -#include <linux/ds1286.h> +#include <linux/rtc/ds1286.h> #include <linux/io.h> #include <linux/slab.h> -#define DRV_VERSION "1.0" - struct ds1286_priv { struct rtc_device *rtc; u32 __iomem *rtcregs; @@ -363,5 +361,4 @@ module_platform_driver(ds1286_platform_driver); MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); MODULE_DESCRIPTION("DS1286 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-ds1286"); diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 6bef7a5233c4..f5dd09fe5add 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -9,16 +9,16 @@ * this archive for more details. */ +#include <linux/bcd.h> #include <linux/init.h> -#include <linux/module.h> +#include <linux/io.h> #include <linux/kernel.h> -#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> #include <linux/rtc.h> -#include <linux/io.h> -#include <linux/bcd.h> +#include <linux/spi/spi.h> #define DRV_NAME "rtc-ds1302" -#define DRV_VERSION "0.1.1" #define RTC_CMD_READ 0x81 /* Read command */ #define RTC_CMD_WRITE 0x80 /* Write command */ @@ -28,6 +28,8 @@ #define RTC_ADDR_RAM0 0x20 /* Address of RAM0 */ #define RTC_ADDR_TCR 0x08 /* Address of trickle charge register */ +#define RTC_CLCK_BURST 0x1F /* Address of clock burst */ +#define RTC_CLCK_LEN 0x08 /* Size of clock burst */ #define RTC_ADDR_CTRL 0x07 /* Address of control register */ #define RTC_ADDR_YEAR 0x06 /* Address of year register */ #define RTC_ADDR_DAY 0x05 /* Address of day of week register */ @@ -37,219 +39,181 @@ #define RTC_ADDR_MIN 0x01 /* Address of minute register */ #define RTC_ADDR_SEC 0x00 /* Address of second register */ -#ifdef CONFIG_SH_SECUREEDGE5410 -#include <asm/rtc.h> -#include <mach/secureedge5410.h> - -#define RTC_RESET 0x1000 -#define RTC_IODATA 0x0800 -#define RTC_SCLK 0x0400 - -#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) -#define get_dp() SECUREEDGE_READ_IOPORT() -#define ds1302_set_tx() -#define ds1302_set_rx() - -static inline int ds1302_hw_init(void) +static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *time) { - return 0; + struct spi_device *spi = dev_get_drvdata(dev); + u8 buf[1 + RTC_CLCK_LEN]; + u8 *bp = buf; + int status; + + /* Enable writing */ + bp = buf; + *bp++ = RTC_ADDR_CTRL << 1 | RTC_CMD_WRITE; + *bp++ = RTC_CMD_WRITE_ENABLE; + + status = spi_write_then_read(spi, buf, 2, + NULL, 0); + if (status) + return status; + + /* Write registers starting at the first time/date address. */ + bp = buf; + *bp++ = RTC_CLCK_BURST << 1 | RTC_CMD_WRITE; + + *bp++ = bin2bcd(time->tm_sec); + *bp++ = bin2bcd(time->tm_min); + *bp++ = bin2bcd(time->tm_hour); + *bp++ = bin2bcd(time->tm_mday); + *bp++ = bin2bcd(time->tm_mon + 1); + *bp++ = time->tm_wday + 1; + *bp++ = bin2bcd(time->tm_year % 100); + *bp++ = RTC_CMD_WRITE_DISABLE; + + /* use write-then-read since dma from stack is nonportable */ + return spi_write_then_read(spi, buf, sizeof(buf), + NULL, 0); } -static inline void ds1302_reset(void) +static int ds1302_rtc_get_time(struct device *dev, struct rtc_time *time) { - set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); + struct spi_device *spi = dev_get_drvdata(dev); + u8 addr = RTC_CLCK_BURST << 1 | RTC_CMD_READ; + u8 buf[RTC_CLCK_LEN - 1]; + int status; + + /* Use write-then-read to get all the date/time registers + * since dma from stack is nonportable + */ + status = spi_write_then_read(spi, &addr, sizeof(addr), + buf, sizeof(buf)); + if (status < 0) + return status; + + /* Decode the registers */ + time->tm_sec = bcd2bin(buf[RTC_ADDR_SEC]); + time->tm_min = bcd2bin(buf[RTC_ADDR_MIN]); + time->tm_hour = bcd2bin(buf[RTC_ADDR_HOUR]); + time->tm_wday = buf[RTC_ADDR_DAY] - 1; + time->tm_mday = bcd2bin(buf[RTC_ADDR_DATE]); + time->tm_mon = bcd2bin(buf[RTC_ADDR_MON]) - 1; + time->tm_year = bcd2bin(buf[RTC_ADDR_YEAR]) + 100; + + /* Time may not be set */ + return rtc_valid_tm(time); } -static inline void ds1302_clock(void) -{ - set_dp(get_dp() | RTC_SCLK); /* clock high */ - set_dp(get_dp() & ~RTC_SCLK); /* clock low */ -} - -static inline void ds1302_start(void) -{ - set_dp(get_dp() | RTC_RESET); -} - -static inline void ds1302_stop(void) -{ - set_dp(get_dp() & ~RTC_RESET); -} - -static inline void ds1302_txbit(int bit) -{ - set_dp((get_dp() & ~RTC_IODATA) | (bit ? RTC_IODATA : 0)); -} - -static inline int ds1302_rxbit(void) -{ - return !!(get_dp() & RTC_IODATA); -} - -#else -#error "Add support for your platform" -#endif +static struct rtc_class_ops ds1302_rtc_ops = { + .read_time = ds1302_rtc_get_time, + .set_time = ds1302_rtc_set_time, +}; -static void ds1302_sendbits(unsigned int val) +static int ds1302_probe(struct spi_device *spi) { - int i; - - ds1302_set_tx(); - - for (i = 8; (i); i--, val >>= 1) { - ds1302_txbit(val & 0x1); - ds1302_clock(); + struct rtc_device *rtc; + u8 addr; + u8 buf[4]; + u8 *bp = buf; + int status; + + /* Sanity check board setup data. This may be hooked up + * in 3wire mode, but we don't care. Note that unless + * there's an inverter in place, this needs SPI_CS_HIGH! + */ + if (spi->bits_per_word && (spi->bits_per_word != 8)) { + dev_err(&spi->dev, "bad word length\n"); + return -EINVAL; + } else if (spi->max_speed_hz > 2000000) { + dev_err(&spi->dev, "speed is too high\n"); + return -EINVAL; + } else if (spi->mode & SPI_CPHA) { + dev_err(&spi->dev, "bad mode\n"); + return -EINVAL; } -} - -static unsigned int ds1302_recvbits(void) -{ - unsigned int val; - int i; - - ds1302_set_rx(); - for (i = 0, val = 0; (i < 8); i++) { - val |= (ds1302_rxbit() << i); - ds1302_clock(); + addr = RTC_ADDR_CTRL << 1 | RTC_CMD_READ; + status = spi_write_then_read(spi, &addr, sizeof(addr), buf, 1); + if (status < 0) { + dev_err(&spi->dev, "control register read error %d\n", + status); + return status; } - return val; -} - -static unsigned int ds1302_readbyte(unsigned int addr) -{ - unsigned int val; - - ds1302_reset(); - - ds1302_start(); - ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); - val = ds1302_recvbits(); - ds1302_stop(); - - return val; -} - -static void ds1302_writebyte(unsigned int addr, unsigned int val) -{ - ds1302_reset(); - - ds1302_start(); - ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); - ds1302_sendbits(val); - ds1302_stop(); -} - -static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC)); - tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN)); - tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR)); - tm->tm_wday = bcd2bin(ds1302_readbyte(RTC_ADDR_DAY)); - tm->tm_mday = bcd2bin(ds1302_readbyte(RTC_ADDR_DATE)); - tm->tm_mon = bcd2bin(ds1302_readbyte(RTC_ADDR_MON)) - 1; - tm->tm_year = bcd2bin(ds1302_readbyte(RTC_ADDR_YEAR)); - - if (tm->tm_year < 70) - tm->tm_year += 100; - - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); - - return rtc_valid_tm(tm); -} - -static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - ds1302_writebyte(RTC_ADDR_CTRL, RTC_CMD_WRITE_ENABLE); - /* Stop RTC */ - ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); - - ds1302_writebyte(RTC_ADDR_SEC, bin2bcd(tm->tm_sec)); - ds1302_writebyte(RTC_ADDR_MIN, bin2bcd(tm->tm_min)); - ds1302_writebyte(RTC_ADDR_HOUR, bin2bcd(tm->tm_hour)); - ds1302_writebyte(RTC_ADDR_DAY, bin2bcd(tm->tm_wday)); - ds1302_writebyte(RTC_ADDR_DATE, bin2bcd(tm->tm_mday)); - ds1302_writebyte(RTC_ADDR_MON, bin2bcd(tm->tm_mon + 1)); - ds1302_writebyte(RTC_ADDR_YEAR, bin2bcd(tm->tm_year % 100)); + if ((buf[0] & ~RTC_CMD_WRITE_DISABLE) != 0) { + status = spi_write_then_read(spi, &addr, sizeof(addr), buf, 1); + if (status < 0) { + dev_err(&spi->dev, "control register read error %d\n", + status); + return status; + } + + if ((buf[0] & ~RTC_CMD_WRITE_DISABLE) != 0) { + dev_err(&spi->dev, "junk in control register\n"); + return -ENODEV; + } + } + if (buf[0] == 0) { + bp = buf; + *bp++ = RTC_ADDR_CTRL << 1 | RTC_CMD_WRITE; + *bp++ = RTC_CMD_WRITE_DISABLE; + + status = spi_write_then_read(spi, buf, 2, NULL, 0); + if (status < 0) { + dev_err(&spi->dev, "control register write error %d\n", + status); + return status; + } + + addr = RTC_ADDR_CTRL << 1 | RTC_CMD_READ; + status = spi_write_then_read(spi, &addr, sizeof(addr), buf, 1); + if (status < 0) { + dev_err(&spi->dev, + "error %d reading control register\n", + status); + return status; + } + + if (buf[0] != RTC_CMD_WRITE_DISABLE) { + dev_err(&spi->dev, "failed to detect chip\n"); + return -ENODEV; + } + } - /* Start RTC */ - ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); + spi_set_drvdata(spi, spi); - ds1302_writebyte(RTC_ADDR_CTRL, RTC_CMD_WRITE_DISABLE); + rtc = devm_rtc_device_register(&spi->dev, "ds1302", + &ds1302_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + status = PTR_ERR(rtc); + dev_err(&spi->dev, "error %d registering rtc\n", status); + return status; + } return 0; } -static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, - unsigned long arg) +static int ds1302_remove(struct spi_device *spi) { - switch (cmd) { -#ifdef RTC_SET_CHARGE - case RTC_SET_CHARGE: - { - int tcs_val; - - if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) - return -EFAULT; - - ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); - return 0; - } -#endif - } - - return -ENOIOCTLCMD; + spi_set_drvdata(spi, NULL); + return 0; } -static struct rtc_class_ops ds1302_rtc_ops = { - .read_time = ds1302_rtc_read_time, - .set_time = ds1302_rtc_set_time, - .ioctl = ds1302_rtc_ioctl, +#ifdef CONFIG_OF +static const struct of_device_id ds1302_dt_ids[] = { + { .compatible = "maxim,ds1302", }, + { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, ds1302_dt_ids); +#endif -static int __init ds1302_rtc_probe(struct platform_device *pdev) -{ - struct rtc_device *rtc; - - if (ds1302_hw_init()) { - dev_err(&pdev->dev, "Failed to init communication channel"); - return -EINVAL; - } - - /* Reset */ - ds1302_reset(); - - /* Write a magic value to the DS1302 RAM, and see if it sticks. */ - ds1302_writebyte(RTC_ADDR_RAM0, 0x42); - if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) { - dev_err(&pdev->dev, "Failed to probe"); - return -ENODEV; - } - - rtc = devm_rtc_device_register(&pdev->dev, "ds1302", - &ds1302_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - platform_set_drvdata(pdev, rtc); - - return 0; -} - -static struct platform_driver ds1302_platform_driver = { - .driver = { - .name = DRV_NAME, - }, +static struct spi_driver ds1302_driver = { + .driver.name = "rtc-ds1302", + .driver.of_match_table = of_match_ptr(ds1302_dt_ids), + .probe = ds1302_probe, + .remove = ds1302_remove, }; -module_platform_driver_probe(ds1302_platform_driver, ds1302_rtc_probe); +module_spi_driver(ds1302_driver); MODULE_DESCRIPTION("Dallas DS1302 RTC driver"); -MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR("Paul Mundt, David McCullough"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 8e41c4613e51..72b22935eb62 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -313,13 +313,6 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]); alm->time.tm_min = bcd2bin(buf[DS1305_MIN]); alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]); - alm->time.tm_mday = -1; - alm->time.tm_mon = -1; - alm->time.tm_year = -1; - /* next three fields are unused by Linux */ - alm->time.tm_wday = -1; - alm->time.tm_mday = -1; - alm->time.tm_isdst = -1; return 0; } diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index ecb7dbae9be9..8e1c5cb6ece6 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -275,9 +275,13 @@ static s32 ds1307_native_smbus_write_block_data(const struct i2c_client *client, { u8 suboffset = 0; - if (length <= I2C_SMBUS_BLOCK_MAX) - return i2c_smbus_write_i2c_block_data(client, + if (length <= I2C_SMBUS_BLOCK_MAX) { + s32 retval = i2c_smbus_write_i2c_block_data(client, command, length, values); + if (retval < 0) + return retval; + return length; + } while (suboffset < length) { s32 retval = i2c_smbus_write_i2c_block_data(client, @@ -478,11 +482,6 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); - t->time.tm_mon = -1; - t->time.tm_year = -1; - t->time.tm_wday = -1; - t->time.tm_yday = -1; - t->time.tm_isdst = -1; /* ... and status */ t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); @@ -538,12 +537,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) buf[5] = 0; buf[6] = 0; - /* optionally enable ALARM1 */ + /* disable alarms */ buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); - if (t->enabled) { - dev_dbg(dev, "alarm IRQ armed\n"); - buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ - } buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); ret = ds1307->write_block_data(client, @@ -553,6 +548,13 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) return ret; } + /* optionally enable ALARM1 */ + if (t->enabled) { + dev_dbg(dev, "alarm IRQ armed\n"); + buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ + i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, buf[7]); + } + return 0; } @@ -595,6 +597,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { * Alarm support for mcp794xx devices. */ +#define MCP794XX_REG_WEEKDAY 0x3 +#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7 #define MCP794XX_REG_CONTROL 0x07 # define MCP794XX_BIT_ALM0_EN 0x10 # define MCP794XX_BIT_ALM1_EN 0x20 @@ -1144,12 +1148,10 @@ static struct clk_init_data ds3231_clks_init[] = { [DS3231_CLK_SQW] = { .name = "ds3231_clk_sqw", .ops = &ds3231_clk_sqw_ops, - .flags = CLK_IS_ROOT, }, [DS3231_CLK_32KHZ] = { .name = "ds3231_clk_32khz", .ops = &ds3231_clk_32khz_ops, - .flags = CLK_IS_ROOT, }, }; @@ -1226,13 +1228,16 @@ static int ds1307_probe(struct i2c_client *client, { struct ds1307 *ds1307; int err = -ENODEV; - int tmp; + int tmp, wday; struct chip_desc *chip = &chips[id->driver_data]; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); bool want_irq = false; bool ds1307_can_wakeup_device = false; unsigned char *buf; struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); + struct rtc_time tm; + unsigned long timestamp; + irq_handler_t irq_handler = ds1307_irq; static const int bbsqi_bitpos[] = { @@ -1521,6 +1526,27 @@ read_rtc: bin2bcd(tmp)); } + /* + * Some IPs have weekday reset value = 0x1 which might not correct + * hence compute the wday using the current date/month/year values + */ + ds1307_get_time(&client->dev, &tm); + wday = tm.tm_wday; + timestamp = rtc_tm_to_time64(&tm); + rtc_time64_to_tm(timestamp, &tm); + + /* + * Check if reset wday is different from the computed wday + * If different then set the wday which we computed using + * timestamp + */ + if (wday != tm.tm_wday) { + wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY); + wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK; + wday = wday | (tm.tm_wday + 1); + i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday); + } + if (want_irq) { device_set_wakeup_capable(&client->dev, true); set_bit(HAS_ALARM, &ds1307->flags); diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 3d389bd8a289..895fbeeb47fe 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -24,7 +24,6 @@ #include <linux/pm_wakeirq.h> #include <linux/slab.h> -#define DS1343_DRV_VERSION "01.00" #define DALLAS_MAXIM_DS1343 0 #define DALLAS_MAXIM_DS1344 1 @@ -505,12 +504,6 @@ static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour; alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday; - alarm->time.tm_mon = -1; - alarm->time.tm_year = -1; - alarm->time.tm_wday = -1; - alarm->time.tm_yday = -1; - alarm->time.tm_isdst = -1; - out: mutex_unlock(&priv->mutex); return res; @@ -747,4 +740,3 @@ MODULE_DESCRIPTION("DS1343 RTC SPI Driver"); MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>," "Ankur Srivastava <sankurece@gmail.com>"); MODULE_LICENSE("GPL v2"); -MODULE_VERSION(DS1343_DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index da3d04ce83bd..1b2dcb58c0ab 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -25,8 +25,6 @@ #include <linux/io.h> #include <linux/module.h> -#define DRV_VERSION "0.6" - enum ds1511reg { DS1511_SEC = 0x0, DS1511_MIN = 0x1, @@ -537,4 +535,3 @@ module_platform_driver(ds1511_rtc_driver); MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>"); MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 38422ab4ec5a..9961ec646fd2 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -20,8 +20,6 @@ #include <linux/io.h> #include <linux/module.h> -#define DRV_VERSION "0.3" - #define RTC_REG_SIZE 0x2000 #define RTC_OFFSET 0x1ff0 @@ -359,4 +357,3 @@ module_platform_driver(ds1553_rtc_driver); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("Dallas DS1553 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 92b1cbf2c4a7..5c18ac7394c4 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -13,8 +13,6 @@ #include <linux/rtc.h> #include <linux/module.h> -#define DRV_VERSION "0.4" - /* Registers */ #define DS1672_REG_CNT_BASE 0 @@ -165,8 +163,6 @@ static int ds1672_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = devm_rtc_device_register(&client->dev, ds1672_driver.driver.name, &ds1672_rtc_ops, THIS_MODULE); @@ -213,4 +209,3 @@ module_i2c_driver(ds1672_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 1e6cfc84b1f6..ed43b4311660 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -32,8 +32,6 @@ #include <linux/proc_fs.h> #endif -#define DRV_VERSION "0.42.0" - /* ----------------------------------------------------------------------- */ /* Standard read/write functions if platform does not provide overrides */ @@ -105,6 +103,26 @@ ds1685_rtc_bin2bcd(struct ds1685_priv *rtc, u8 val, u8 bin_mask, u8 bcd_mask) } /** + * s1685_rtc_check_mday - check validity of the day of month. + * @rtc: pointer to the ds1685 rtc structure. + * @mday: day of month. + * + * Returns -EDOM if the day of month is not within 1..31 range. + */ +static inline int +ds1685_rtc_check_mday(struct ds1685_priv *rtc, u8 mday) +{ + if (rtc->bcd_mode) { + if (mday < 0x01 || mday > 0x31 || (mday & 0x0f) > 0x09) + return -EDOM; + } else { + if (mday < 1 || mday > 31) + return -EDOM; + } + return 0; +} + +/** * ds1685_rtc_switch_to_bank0 - switch the rtc to bank 0. * @rtc: pointer to the ds1685 rtc structure. */ @@ -379,6 +397,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct platform_device *pdev = to_platform_device(dev); struct ds1685_priv *rtc = platform_get_drvdata(pdev); u8 seconds, minutes, hours, mday, ctrlb, ctrlc; + int ret; /* Fetch the alarm info from the RTC alarm registers. */ ds1685_rtc_begin_data_access(rtc); @@ -390,34 +409,29 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ctrlc = rtc->read(rtc, RTC_CTRL_C); ds1685_rtc_end_data_access(rtc); - /* Check month date. */ - if (!(mday >= 1) && (mday <= 31)) - return -EDOM; + /* Check the month date for validity. */ + ret = ds1685_rtc_check_mday(rtc, mday); + if (ret) + return ret; /* * Check the three alarm bytes. * * The Linux RTC system doesn't support the "don't care" capability * of this RTC chip. We check for it anyways in case support is - * added in the future. + * added in the future and only assign when we care. */ - if (unlikely(seconds >= 0xc0)) - alrm->time.tm_sec = -1; - else + if (likely(seconds < 0xc0)) alrm->time.tm_sec = ds1685_rtc_bcd2bin(rtc, seconds, RTC_SECS_BCD_MASK, RTC_SECS_BIN_MASK); - if (unlikely(minutes >= 0xc0)) - alrm->time.tm_min = -1; - else + if (likely(minutes < 0xc0)) alrm->time.tm_min = ds1685_rtc_bcd2bin(rtc, minutes, RTC_MINS_BCD_MASK, RTC_MINS_BIN_MASK); - if (unlikely(hours >= 0xc0)) - alrm->time.tm_hour = -1; - else + if (likely(hours < 0xc0)) alrm->time.tm_hour = ds1685_rtc_bcd2bin(rtc, hours, RTC_HRS_24_BCD_MASK, RTC_HRS_24_BIN_MASK); @@ -425,11 +439,6 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) /* Write the data to rtc_wkalrm. */ alrm->time.tm_mday = ds1685_rtc_bcd2bin(rtc, mday, RTC_MDAY_BCD_MASK, RTC_MDAY_BIN_MASK); - alrm->time.tm_mon = -1; - alrm->time.tm_year = -1; - alrm->time.tm_wday = -1; - alrm->time.tm_yday = -1; - alrm->time.tm_isdst = -1; alrm->enabled = !!(ctrlb & RTC_CTRL_B_AIE); alrm->pending = !!(ctrlc & RTC_CTRL_C_AF); @@ -447,6 +456,7 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct platform_device *pdev = to_platform_device(dev); struct ds1685_priv *rtc = platform_get_drvdata(pdev); u8 ctrlb, seconds, minutes, hours, mday; + int ret; /* Fetch the alarm info and convert to BCD. */ seconds = ds1685_rtc_bin2bcd(rtc, alrm->time.tm_sec, @@ -463,8 +473,9 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) RTC_MDAY_BCD_MASK); /* Check the month date for validity. */ - if (!(mday >= 1) && (mday <= 31)) - return -EDOM; + ret = ds1685_rtc_check_mday(rtc, mday); + if (ret) + return ret; /* * Check the three alarm bytes. @@ -2213,6 +2224,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev) (ctrl4a | RTC_CTRL_4A_PAB)); /* Spin ... we do not switch back to bank0. */ + while(1); unreachable(); } } @@ -2224,5 +2236,4 @@ MODULE_AUTHOR("Joshua Kinard <kumba@gentoo.org>"); MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd-electronics.com>"); MODULE_DESCRIPTION("Dallas/Maxim DS1685/DS1687-series RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-ds1685"); diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index c5168b3bcf1a..3abf1cbfb8ce 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -24,8 +24,6 @@ #include <linux/io.h> #include <linux/module.h> -#define DRV_VERSION "0.4" - #define RTC_SIZE 8 #define RTC_CONTROL 0 @@ -239,5 +237,4 @@ module_platform_driver(ds1742_rtc_driver); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("Dallas DS1742 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-ds1742"); diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 16310fe79d76..9a1582ed7070 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c @@ -13,7 +13,7 @@ #include <linux/rtc.h> #include <linux/types.h> #include <linux/bcd.h> -#include <linux/rtc-ds2404.h> +#include <linux/platform_data/rtc-ds2404.h> #include <linux/delay.h> #include <linux/gpio.h> #include <linux/slab.h> diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 7edc889729c5..b1f20d8c358f 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -197,12 +197,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F); alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F); - alarm->time.tm_mon = -1; - alarm->time.tm_year = -1; - alarm->time.tm_wday = -1; - alarm->time.tm_yday = -1; - alarm->time.tm_isdst = -1; - alarm->enabled = !!(control & DS3232_REG_CR_A1IE); alarm->pending = !!(stat & DS3232_REG_SR_A1F); @@ -369,6 +363,11 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, if (ret) return ret; + ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops, + THIS_MODULE); + if (IS_ERR(ds3232->rtc)) + return PTR_ERR(ds3232->rtc); + if (ds3232->irq > 0) { ret = devm_request_threaded_irq(dev, ds3232->irq, NULL, ds3232_irq, @@ -380,10 +379,8 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, } else device_init_wakeup(dev, 1); } - ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops, - THIS_MODULE); - return PTR_ERR_OR_ZERO(ds3232->rtc); + return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index 96d38609d803..0130afd7fe88 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c @@ -259,6 +259,12 @@ static const struct rtc_class_ops efi_rtc_ops = { static int __init efi_rtc_probe(struct platform_device *dev) { struct rtc_device *rtc; + efi_time_t eft; + efi_time_cap_t cap; + + /* First check if the RTC is usable */ + if (efi.get_time(&eft, &cap) != EFI_SUCCESS) + return -ENODEV; rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index a1628adf9f52..694038208745 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c @@ -28,8 +28,6 @@ #define EP93XX_RTC_SWCOMP_INT_MASK 0x0000ffff #define EP93XX_RTC_SWCOMP_INT_SHIFT 0 -#define DRV_VERSION "0.3" - /* * struct device dev.platform_data is used to store our private data * because struct rtc_device does not have a variable to hold it. @@ -184,5 +182,4 @@ module_platform_driver(ep93xx_rtc_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("EP93XX RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:ep93xx-rtc"); diff --git a/drivers/rtc/rtc-gemini.c b/drivers/rtc/rtc-gemini.c index f46b6d46a51b..b57505efadbc 100644 --- a/drivers/rtc/rtc-gemini.c +++ b/drivers/rtc/rtc-gemini.c @@ -28,7 +28,6 @@ #include <linux/module.h> #define DRV_NAME "rtc-gemini" -#define DRV_VERSION "0.2" MODULE_AUTHOR("Hans Ulli Kroll <ulli.kroll@googlemail.com>"); MODULE_DESCRIPTION("RTC driver for Gemini SoC"); diff --git a/drivers/rtc/rtc-generic.c b/drivers/rtc/rtc-generic.c index d726c6aa96a8..1bf5d2347928 100644 --- a/drivers/rtc/rtc-generic.c +++ b/drivers/rtc/rtc-generic.c @@ -9,44 +9,10 @@ #include <linux/platform_device.h> #include <linux/rtc.h> -#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \ - defined(CONFIG_PPC) || defined(CONFIG_SUPERH32) -#include <asm/rtc.h> - -static int generic_get_time(struct device *dev, struct rtc_time *tm) -{ - unsigned int ret = get_rtc_time(tm); - - if (ret & RTC_BATT_BAD) - return -EOPNOTSUPP; - - return rtc_valid_tm(tm); -} - -static int generic_set_time(struct device *dev, struct rtc_time *tm) -{ - if (set_rtc_time(tm) < 0) - return -EOPNOTSUPP; - - return 0; -} - -static const struct rtc_class_ops generic_rtc_ops = { - .read_time = generic_get_time, - .set_time = generic_set_time, -}; -#else -#define generic_rtc_ops *(struct rtc_class_ops*)NULL -#endif - static int __init generic_rtc_probe(struct platform_device *dev) { struct rtc_device *rtc; - const struct rtc_class_ops *ops; - - ops = dev_get_platdata(&dev->dev); - if (!ops) - ops = &generic_rtc_ops; + const struct rtc_class_ops *ops = dev_get_platdata(&dev->dev); rtc = devm_rtc_device_register(&dev->dev, "rtc-generic", ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index b1b4746a0eab..e5ad527cb75e 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -198,7 +198,7 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) return ret; /* The alarm only has a minute accuracy */ - alm_tm->tm_sec = -1; + alm_tm->tm_sec = 0; alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ? -1 : @@ -213,9 +213,6 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) -1 : bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK); - alm_tm->tm_mon = -1; - alm_tm->tm_year = -1; - ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2); if (ret < 0) return ret; @@ -413,7 +410,7 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563) init.name = "hym8563-clkout"; init.ops = &hym8563_clkout_ops; - init.flags = CLK_IS_ROOT; + init.flags = 0; init.parent_names = NULL; init.num_parents = 0; hym8563->clkout_hw.init = &init; diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 839d1fd63cd7..38586a024ee8 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -20,8 +20,6 @@ #include <linux/of.h> #include <linux/of_device.h> -#define DRV_VERSION "0.1" - /* ISL register offsets */ #define ISL12022_REG_SC 0x00 #define ISL12022_REG_MN 0x01 @@ -258,8 +256,6 @@ static int isl12022_probe(struct i2c_client *client, if (!isl12022) return -ENOMEM; - dev_dbg(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - i2c_set_clientdata(client, isl12022); isl12022->rtc = devm_rtc_device_register(&client->dev, @@ -299,4 +295,3 @@ module_i2c_driver(isl12022_driver); MODULE_AUTHOR("roman.fietze@telemotive.de"); MODULE_DESCRIPTION("ISL 12022 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c index 54328d4ac0d3..0e7f0f52bfe4 100644 --- a/drivers/rtc/rtc-isl12057.c +++ b/drivers/rtc/rtc-isl12057.c @@ -245,8 +245,7 @@ static int isl12057_rtc_update_alarm(struct device *dev, int enable) static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct isl12057_rtc_data *data = dev_get_drvdata(dev); - struct rtc_time rtc_tm, *alarm_tm = &alarm->time; - unsigned long rtc_secs, alarm_secs; + struct rtc_time *alarm_tm = &alarm->time; u8 regs[ISL12057_A1_SEC_LEN]; unsigned int ir; int ret; @@ -264,36 +263,6 @@ static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) alarm_tm->tm_min = bcd2bin(regs[1] & 0x7f); alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f); alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f); - alarm_tm->tm_wday = -1; - - /* - * The alarm section does not store year/month. We use the ones in rtc - * section as a basis and increment month and then year if needed to get - * alarm after current time. - */ - ret = _isl12057_rtc_read_time(dev, &rtc_tm); - if (ret) - goto err_unlock; - - alarm_tm->tm_year = rtc_tm.tm_year; - alarm_tm->tm_mon = rtc_tm.tm_mon; - - ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); - if (ret) - goto err_unlock; - - ret = rtc_tm_to_time(alarm_tm, &alarm_secs); - if (ret) - goto err_unlock; - - if (alarm_secs < rtc_secs) { - if (alarm_tm->tm_mon == 11) { - alarm_tm->tm_mon = 0; - alarm_tm->tm_year += 1; - } else { - alarm_tm->tm_mon += 1; - } - } ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir); if (ret) { diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index b57a304ff62c..2893785f0eba 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -15,8 +15,6 @@ #include <linux/bcd.h> #include <linux/rtc.h> -#define DRV_VERSION "0.3" - /* Register map */ /* rtc section */ #define ISL1208_REG_SC 0x00 @@ -632,9 +630,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) if (isl1208_i2c_validate_client(client) < 0) return -ENODEV; - dev_info(&client->dev, - "chip found, driver version " DRV_VERSION "\n"); - if (client->irq > 0) { rc = devm_request_threaded_irq(&client->dev, client->irq, NULL, isl1208_rtc_interrupt, @@ -706,4 +701,3 @@ module_i2c_driver(isl1208_driver); MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>"); MODULE_DESCRIPTION("Intersil ISL1208 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index d107a8e72a7d..58698d21c2c3 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -32,41 +32,42 @@ #include <linux/watchdog.h> #endif -#define M41T80_REG_SSEC 0 -#define M41T80_REG_SEC 1 -#define M41T80_REG_MIN 2 -#define M41T80_REG_HOUR 3 -#define M41T80_REG_WDAY 4 -#define M41T80_REG_DAY 5 -#define M41T80_REG_MON 6 -#define M41T80_REG_YEAR 7 -#define M41T80_REG_ALARM_MON 0xa -#define M41T80_REG_ALARM_DAY 0xb -#define M41T80_REG_ALARM_HOUR 0xc -#define M41T80_REG_ALARM_MIN 0xd -#define M41T80_REG_ALARM_SEC 0xe -#define M41T80_REG_FLAGS 0xf -#define M41T80_REG_SQW 0x13 +#define M41T80_REG_SSEC 0x00 +#define M41T80_REG_SEC 0x01 +#define M41T80_REG_MIN 0x02 +#define M41T80_REG_HOUR 0x03 +#define M41T80_REG_WDAY 0x04 +#define M41T80_REG_DAY 0x05 +#define M41T80_REG_MON 0x06 +#define M41T80_REG_YEAR 0x07 +#define M41T80_REG_ALARM_MON 0x0a +#define M41T80_REG_ALARM_DAY 0x0b +#define M41T80_REG_ALARM_HOUR 0x0c +#define M41T80_REG_ALARM_MIN 0x0d +#define M41T80_REG_ALARM_SEC 0x0e +#define M41T80_REG_FLAGS 0x0f +#define M41T80_REG_SQW 0x13 #define M41T80_DATETIME_REG_SIZE (M41T80_REG_YEAR + 1) #define M41T80_ALARM_REG_SIZE \ (M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON) -#define M41T80_SEC_ST (1 << 7) /* ST: Stop Bit */ -#define M41T80_ALMON_AFE (1 << 7) /* AFE: AF Enable Bit */ -#define M41T80_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */ -#define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ -#define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ -#define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ -#define M41T80_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */ -#define M41T80_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */ -#define M41T80_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */ - -#define M41T80_FEATURE_HT (1 << 0) /* Halt feature */ -#define M41T80_FEATURE_BL (1 << 1) /* Battery low indicator */ -#define M41T80_FEATURE_SQ (1 << 2) /* Squarewave feature */ -#define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */ -#define M41T80_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */ +#define M41T80_SEC_ST BIT(7) /* ST: Stop Bit */ +#define M41T80_ALMON_AFE BIT(7) /* AFE: AF Enable Bit */ +#define M41T80_ALMON_SQWE BIT(6) /* SQWE: SQW Enable Bit */ +#define M41T80_ALHOUR_HT BIT(6) /* HT: Halt Update Bit */ +#define M41T80_FLAGS_OF BIT(2) /* OF: Oscillator Failure Bit */ +#define M41T80_FLAGS_AF BIT(6) /* AF: Alarm Flag Bit */ +#define M41T80_FLAGS_BATT_LOW BIT(4) /* BL: Battery Low Bit */ +#define M41T80_WATCHDOG_RB2 BIT(7) /* RB: Watchdog resolution */ +#define M41T80_WATCHDOG_RB1 BIT(1) /* RB: Watchdog resolution */ +#define M41T80_WATCHDOG_RB0 BIT(0) /* RB: Watchdog resolution */ + +#define M41T80_FEATURE_HT BIT(0) /* Halt feature */ +#define M41T80_FEATURE_BL BIT(1) /* Battery low indicator */ +#define M41T80_FEATURE_SQ BIT(2) /* Squarewave feature */ +#define M41T80_FEATURE_WD BIT(3) /* Extra watchdog resolution */ +#define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */ static DEFINE_MUTEX(m41t80_rtc_mutex); static const struct i2c_device_id m41t80_id[] = { @@ -90,27 +91,65 @@ struct m41t80_data { struct rtc_device *rtc; }; +static irqreturn_t m41t80_handle_irq(int irq, void *dev_id) +{ + struct i2c_client *client = dev_id; + struct m41t80_data *m41t80 = i2c_get_clientdata(client); + struct mutex *lock = &m41t80->rtc->ops_lock; + unsigned long events = 0; + int flags, flags_afe; + + mutex_lock(lock); + + flags_afe = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); + if (flags_afe < 0) { + mutex_unlock(lock); + return IRQ_NONE; + } + + flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); + if (flags <= 0) { + mutex_unlock(lock); + return IRQ_NONE; + } + + if (flags & M41T80_FLAGS_AF) { + flags &= ~M41T80_FLAGS_AF; + flags_afe &= ~M41T80_ALMON_AFE; + events |= RTC_AF; + } + + if (events) { + rtc_update_irq(m41t80->rtc, 1, events); + i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS, flags); + i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, + flags_afe); + } + + mutex_unlock(lock); + + return IRQ_HANDLED; +} + static int m41t80_get_datetime(struct i2c_client *client, struct rtc_time *tm) { - u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC }; - struct i2c_msg msgs[] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = dt_addr, - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, - .buf = buf + M41T80_REG_SEC, - }, - }; + unsigned char buf[8]; + int err, flags; + + flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); + if (flags < 0) + return flags; + + if (flags & M41T80_FLAGS_OF) { + dev_err(&client->dev, "Oscillator failure, data is invalid.\n"); + return -EINVAL; + } - if (i2c_transfer(client->adapter, msgs, 2) < 0) { - dev_err(&client->dev, "read error\n"); + err = i2c_smbus_read_i2c_block_data(client, M41T80_REG_SSEC, + sizeof(buf), buf); + if (err < 0) { + dev_err(&client->dev, "Unable to read date\n"); return -EIO; } @@ -129,70 +168,42 @@ static int m41t80_get_datetime(struct i2c_client *client, /* Sets the given date and time to the real time clock. */ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) { - u8 wbuf[1 + M41T80_DATETIME_REG_SIZE]; - u8 *buf = &wbuf[1]; - u8 dt_addr[1] = { M41T80_REG_SEC }; - struct i2c_msg msgs_in[] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = dt_addr, - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, - .buf = buf + M41T80_REG_SEC, - }, - }; - struct i2c_msg msgs[] = { - { - .addr = client->addr, - .flags = 0, - .len = 1 + M41T80_DATETIME_REG_SIZE, - .buf = wbuf, - }, - }; + unsigned char buf[8]; + int err, flags; - /* Read current reg values into buf[1..7] */ - if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { - dev_err(&client->dev, "read error\n"); - return -EIO; - } + if (tm->tm_year < 100 || tm->tm_year > 199) + return -EINVAL; - wbuf[0] = 0; /* offset into rtc's regs */ - /* Merge time-data and register flags into buf[0..7] */ buf[M41T80_REG_SSEC] = 0; - buf[M41T80_REG_SEC] = - bin2bcd(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f); - buf[M41T80_REG_MIN] = - bin2bcd(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f); - buf[M41T80_REG_HOUR] = - bin2bcd(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f); - buf[M41T80_REG_WDAY] = - (tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07); - buf[M41T80_REG_DAY] = - bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f); - buf[M41T80_REG_MON] = - bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f); - - /* assume 20YY not 19YY */ - if (tm->tm_year < 100 || tm->tm_year > 199) { - dev_err(&client->dev, "Year must be between 2000 and 2099. It's %d.\n", - tm->tm_year + 1900); - return -EINVAL; + buf[M41T80_REG_SEC] = bin2bcd(tm->tm_sec); + buf[M41T80_REG_MIN] = bin2bcd(tm->tm_min); + buf[M41T80_REG_HOUR] = bin2bcd(tm->tm_hour); + buf[M41T80_REG_DAY] = bin2bcd(tm->tm_mday); + buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1); + buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year - 100); + buf[M41T80_REG_WDAY] = tm->tm_wday; + + err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_SSEC, + sizeof(buf), buf); + if (err < 0) { + dev_err(&client->dev, "Unable to write to date registers\n"); + return err; } - buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100); - if (i2c_transfer(client->adapter, msgs, 1) != 1) { - dev_err(&client->dev, "write error\n"); + /* Clear the OF bit of Flags Register */ + flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); + if (flags < 0) + return flags; + + if (i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS, + flags & ~M41T80_FLAGS_OF)) { + dev_err(&client->dev, "Unable to write flags register\n"); return -EIO; } - return 0; + + return err; } -#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq) { struct i2c_client *client = to_i2c_client(dev); @@ -206,9 +217,6 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq) } return 0; } -#else -#define m41t80_rtc_proc NULL -#endif static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm) { @@ -220,19 +228,139 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm) return m41t80_set_datetime(to_i2c_client(dev), tm); } -/* - * XXX - m41t80 alarm functionality is reported broken. - * until it is fixed, don't register alarm functions. - */ +static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct i2c_client *client = to_i2c_client(dev); + int flags, retval; + + flags = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); + if (flags < 0) + return flags; + + if (enabled) + flags |= M41T80_ALMON_AFE; + else + flags &= ~M41T80_ALMON_AFE; + + retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags); + if (retval < 0) { + dev_err(dev, "Unable to enable alarm IRQ %d\n", retval); + return retval; + } + return 0; +} + +static int m41t80_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 alarmvals[5]; + int ret, err; + + alarmvals[0] = bin2bcd(alrm->time.tm_mon + 1); + alarmvals[1] = bin2bcd(alrm->time.tm_mday); + alarmvals[2] = bin2bcd(alrm->time.tm_hour); + alarmvals[3] = bin2bcd(alrm->time.tm_min); + alarmvals[4] = bin2bcd(alrm->time.tm_sec); + + /* Clear AF and AFE flags */ + ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); + if (ret < 0) + return ret; + err = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, + ret & ~(M41T80_ALMON_AFE)); + if (err < 0) { + dev_err(dev, "Unable to clear AFE bit\n"); + return err; + } + + ret = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); + if (ret < 0) + return ret; + + err = i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS, + ret & ~(M41T80_FLAGS_AF)); + if (err < 0) { + dev_err(dev, "Unable to clear AF bit\n"); + return err; + } + + /* Write the alarm */ + err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_ALARM_MON, + 5, alarmvals); + if (err) + return err; + + /* Enable the alarm interrupt */ + if (alrm->enabled) { + alarmvals[0] |= M41T80_ALMON_AFE; + err = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, + alarmvals[0]); + if (err) + return err; + } + + return 0; +} + +static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 alarmvals[5]; + int flags, ret; + + ret = i2c_smbus_read_i2c_block_data(client, M41T80_REG_ALARM_MON, + 5, alarmvals); + if (ret != 5) + return ret < 0 ? ret : -EIO; + + flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); + if (flags < 0) + return flags; + + alrm->time.tm_sec = bcd2bin(alarmvals[4] & 0x7f); + alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f); + alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f); + alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f); + alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f); + + alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE); + alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled; + + return 0; +} + static struct rtc_class_ops m41t80_rtc_ops = { .read_time = m41t80_rtc_read_time, .set_time = m41t80_rtc_set_time, .proc = m41t80_rtc_proc, }; -#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) -static ssize_t m41t80_sysfs_show_flags(struct device *dev, - struct device_attribute *attr, char *buf) +#ifdef CONFIG_PM_SLEEP +static int m41t80_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (client->irq >= 0 && device_may_wakeup(dev)) + enable_irq_wake(client->irq); + + return 0; +} + +static int m41t80_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (client->irq >= 0 && device_may_wakeup(dev)) + disable_irq_wake(client->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume); + +static ssize_t flags_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); int val; @@ -242,10 +370,10 @@ static ssize_t m41t80_sysfs_show_flags(struct device *dev, return val; return sprintf(buf, "%#x\n", val); } -static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL); +static DEVICE_ATTR_RO(flags); -static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t sqwfreq_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct m41t80_data *clientdata = i2c_get_clientdata(client); @@ -272,14 +400,19 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev, } return sprintf(buf, "%d\n", val); } -static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) + +static ssize_t sqwfreq_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct m41t80_data *clientdata = i2c_get_clientdata(client); int almon, sqw, reg_sqw, rc; - int val = simple_strtoul(buf, NULL, 0); + unsigned long val; + + rc = kstrtoul(buf, 0, &val); + if (rc < 0) + return rc; if (!(clientdata->features & M41T80_FEATURE_SQ)) return -EINVAL; @@ -308,7 +441,7 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, sqw = (sqw & 0x0f) | (val << 4); rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, - almon & ~M41T80_ALMON_SQWE); + almon & ~M41T80_ALMON_SQWE); if (rc < 0) return rc; @@ -318,35 +451,24 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, return rc; rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, - almon | M41T80_ALMON_SQWE); - if (rc <0) + almon | M41T80_ALMON_SQWE); + if (rc < 0) return rc; } return count; } -static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR, - m41t80_sysfs_show_sqwfreq, m41t80_sysfs_set_sqwfreq); +static DEVICE_ATTR_RW(sqwfreq); static struct attribute *attrs[] = { &dev_attr_flags.attr, &dev_attr_sqwfreq.attr, NULL, }; + static struct attribute_group attr_group = { .attrs = attrs, }; -static int m41t80_sysfs_register(struct device *dev) -{ - return sysfs_create_group(&dev->kobj, &attr_group); -} -#else -static int m41t80_sysfs_register(struct device *dev) -{ - return 0; -} -#endif - #ifdef CONFIG_RTC_DRV_M41T80_WDT /* ***************************************************************************** @@ -394,7 +516,7 @@ static void wdt_ping(void) /* * WDS = 1 (0x80), mulitplier = WD_TIMO, resolution = 1s (0x02) */ - i2c_data[1] = wdt_margin<<2 | 0x82; + i2c_data[1] = wdt_margin << 2 | 0x82; /* * M41T65 has three bits for watchdog resolution. Don't set bit 7, as @@ -636,49 +758,76 @@ static struct notifier_block wdt_notifier = { * ***************************************************************************** */ + +static void m41t80_remove_sysfs_group(void *_dev) +{ + struct device *dev = _dev; + + sysfs_remove_group(&dev->kobj, &attr_group); +} + static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); int rc = 0; struct rtc_device *rtc = NULL; struct rtc_time tm; - struct m41t80_data *clientdata = NULL; + struct m41t80_data *m41t80_data = NULL; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C - | I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK | + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n"); return -ENODEV; + } - clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata), - GFP_KERNEL); - if (!clientdata) + m41t80_data = devm_kzalloc(&client->dev, sizeof(*m41t80_data), + GFP_KERNEL); + if (!m41t80_data) return -ENOMEM; - clientdata->features = id->driver_data; - i2c_set_clientdata(client, clientdata); + m41t80_data->features = id->driver_data; + i2c_set_clientdata(client, m41t80_data); + + if (client->irq > 0) { + rc = devm_request_threaded_irq(&client->dev, client->irq, + NULL, m41t80_handle_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "m41t80", client); + if (rc) { + dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n"); + client->irq = 0; + } else { + m41t80_rtc_ops.read_alarm = m41t80_read_alarm; + m41t80_rtc_ops.set_alarm = m41t80_set_alarm; + m41t80_rtc_ops.alarm_irq_enable = m41t80_alarm_irq_enable; + /* Enable the wakealarm */ + device_init_wakeup(&client->dev, true); + } + } rtc = devm_rtc_device_register(&client->dev, client->name, - &m41t80_rtc_ops, THIS_MODULE); + &m41t80_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); - clientdata->rtc = rtc; + m41t80_data->rtc = rtc; /* Make sure HT (Halt Update) bit is cleared */ rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR); if (rc >= 0 && rc & M41T80_ALHOUR_HT) { - if (clientdata->features & M41T80_FEATURE_HT) { + if (m41t80_data->features & M41T80_FEATURE_HT) { m41t80_get_datetime(client, &tm); dev_info(&client->dev, "HT bit was set!\n"); dev_info(&client->dev, - "Power Down at " - "%04i-%02i-%02i %02i:%02i:%02i\n", + "Power Down at %04i-%02i-%02i %02i:%02i:%02i\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_HOUR, - rc & ~M41T80_ALHOUR_HT); + rc & ~M41T80_ALHOUR_HT); } if (rc < 0) { @@ -691,18 +840,29 @@ static int m41t80_probe(struct i2c_client *client, if (rc >= 0 && rc & M41T80_SEC_ST) rc = i2c_smbus_write_byte_data(client, M41T80_REG_SEC, - rc & ~M41T80_SEC_ST); + rc & ~M41T80_SEC_ST); if (rc < 0) { dev_err(&client->dev, "Can't clear ST bit\n"); return rc; } - rc = m41t80_sysfs_register(&client->dev); - if (rc) + /* Export sysfs entries */ + rc = sysfs_create_group(&(&client->dev)->kobj, &attr_group); + if (rc) { + dev_err(&client->dev, "Failed to create sysfs group: %d\n", rc); return rc; + } + + rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group, + &client->dev); + if (rc) { + dev_err(&client->dev, + "Failed to add sysfs cleanup action: %d\n", rc); + return rc; + } #ifdef CONFIG_RTC_DRV_M41T80_WDT - if (clientdata->features & M41T80_FEATURE_HT) { + if (m41t80_data->features & M41T80_FEATURE_HT) { save_client = client; rc = misc_register(&wdt_dev); if (rc) @@ -734,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client) static struct i2c_driver m41t80_driver = { .driver = { .name = "rtc-m41t80", + .pm = &m41t80_pm, }, .probe = m41t80_probe, .remove = m41t80_remove, diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index c62b51217ecf..810f4ea481e4 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -22,8 +22,6 @@ #include <linux/io.h> #include <linux/err.h> -#define DRV_VERSION "1.0" - struct m48t35_rtc { u8 pad[0x7ff8]; /* starts at 0x7ff8 */ u8 control; @@ -190,5 +188,4 @@ module_platform_driver(m48t35_platform_driver); MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); MODULE_DESCRIPTION("M48T35 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-m48t35"); diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index a17b7a3ceece..0eeb5714c00f 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -16,7 +16,7 @@ #include <linux/module.h> #include <linux/rtc.h> #include <linux/platform_device.h> -#include <linux/m48t86.h> +#include <linux/platform_data/rtc-m48t86.h> #include <linux/bcd.h> #define M48T86_REG_SEC 0x00 @@ -39,9 +39,6 @@ #define M48T86_REG_B_SET (1 << 7) #define M48T86_REG_D_VRT (1 << 7) -#define DRV_VERSION "0.1" - - static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) { unsigned char reg; @@ -178,5 +175,4 @@ module_platform_driver(m48t86_rtc_platform_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("M48T86 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-m48t86"); diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index b2a76077bbfa..48b6b411f8b2 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -17,8 +17,6 @@ #include <linux/rtc.h> #include <linux/delay.h> -#define DRV_VERSION "0.2" - /* * register indices */ @@ -218,8 +216,6 @@ max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = devm_rtc_device_register(&client->dev, max6900_driver.driver.name, &max6900_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) @@ -249,4 +245,3 @@ module_i2c_driver(max6900_driver); MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-max6916.c b/drivers/rtc/rtc-max6916.c new file mode 100644 index 000000000000..623ab27b2757 --- /dev/null +++ b/drivers/rtc/rtc-max6916.c @@ -0,0 +1,164 @@ +/* rtc-max6916.c + * + * Driver for MAXIM max6916 Low Current, SPI Compatible + * Real Time Clock + * + * Author : Venkat Prashanth B U <venkat.prashanth2498@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/spi/spi.h> +#include <linux/bcd.h> + +/* Registers in max6916 rtc */ + +#define MAX6916_SECONDS_REG 0x01 +#define MAX6916_MINUTES_REG 0x02 +#define MAX6916_HOURS_REG 0x03 +#define MAX6916_DATE_REG 0x04 +#define MAX6916_MONTH_REG 0x05 +#define MAX6916_DAY_REG 0x06 +#define MAX6916_YEAR_REG 0x07 +#define MAX6916_CONTROL_REG 0x08 +#define MAX6916_STATUS_REG 0x0C +#define MAX6916_CLOCK_BURST 0x3F + +static int max6916_read_reg(struct device *dev, unsigned char address, + unsigned char *data) +{ + struct spi_device *spi = to_spi_device(dev); + + *data = address | 0x80; + + return spi_write_then_read(spi, data, 1, data, 1); +} + +static int max6916_write_reg(struct device *dev, unsigned char address, + unsigned char data) +{ + struct spi_device *spi = to_spi_device(dev); + unsigned char buf[2]; + + buf[0] = address & 0x7F; + buf[1] = data; + + return spi_write_then_read(spi, buf, 2, NULL, 0); +} + +static int max6916_read_time(struct device *dev, struct rtc_time *dt) +{ + struct spi_device *spi = to_spi_device(dev); + int err; + unsigned char buf[8]; + + buf[0] = MAX6916_CLOCK_BURST | 0x80; + + err = spi_write_then_read(spi, buf, 1, buf, 8); + + if (err) + return err; + + dt->tm_sec = bcd2bin(buf[0]); + dt->tm_min = bcd2bin(buf[1]); + dt->tm_hour = bcd2bin(buf[2] & 0x3F); + dt->tm_mday = bcd2bin(buf[3]); + dt->tm_mon = bcd2bin(buf[4]) - 1; + dt->tm_wday = bcd2bin(buf[5]) - 1; + dt->tm_year = bcd2bin(buf[6]) + 100; + + return rtc_valid_tm(dt); +} + +static int max6916_set_time(struct device *dev, struct rtc_time *dt) +{ + struct spi_device *spi = to_spi_device(dev); + unsigned char buf[9]; + + if (dt->tm_year < 100 || dt->tm_year > 199) { + dev_err(&spi->dev, "Year must be between 2000 and 2099. It's %d.\n", + dt->tm_year + 1900); + return -EINVAL; + } + + buf[0] = MAX6916_CLOCK_BURST & 0x7F; + buf[1] = bin2bcd(dt->tm_sec); + buf[2] = bin2bcd(dt->tm_min); + buf[3] = (bin2bcd(dt->tm_hour) & 0X3F); + buf[4] = bin2bcd(dt->tm_mday); + buf[5] = bin2bcd(dt->tm_mon + 1); + buf[6] = bin2bcd(dt->tm_wday + 1); + buf[7] = bin2bcd(dt->tm_year % 100); + buf[8] = bin2bcd(0x00); + + /* write the rtc settings */ + return spi_write_then_read(spi, buf, 9, NULL, 0); +} + +static const struct rtc_class_ops max6916_rtc_ops = { + .read_time = max6916_read_time, + .set_time = max6916_set_time, +}; + +static int max6916_probe(struct spi_device *spi) +{ + struct rtc_device *rtc; + unsigned char data; + int res; + + /* spi setup with max6916 in mode 3 and bits per word as 8 */ + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + /* RTC Settings */ + res = max6916_read_reg(&spi->dev, MAX6916_SECONDS_REG, &data); + if (res) + return res; + + /* Disable the write protect of rtc */ + max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data); + data = data & ~(1 << 7); + max6916_write_reg(&spi->dev, MAX6916_CONTROL_REG, data); + + /*Enable oscillator,disable oscillator stop flag, glitch filter*/ + max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data); + data = data & 0x1B; + max6916_write_reg(&spi->dev, MAX6916_STATUS_REG, data); + + /* display the settings */ + max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data); + dev_info(&spi->dev, "MAX6916 RTC CTRL Reg = 0x%02x\n", data); + + max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data); + dev_info(&spi->dev, "MAX6916 RTC Status Reg = 0x%02x\n", data); + + rtc = devm_rtc_device_register(&spi->dev, "max6916", + &max6916_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + spi_set_drvdata(spi, rtc); + + return 0; +} + +static struct spi_driver max6916_driver = { + .driver = { + .name = "max6916", + }, + .probe = max6916_probe, +}; +module_spi_driver(max6916_driver); + +MODULE_DESCRIPTION("MAX6916 SPI RTC DRIVER"); +MODULE_AUTHOR("Venkat Prashanth B U <venkat.prashanth2498@gmail.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index a65868065743..30b8ef6a3676 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -250,18 +250,6 @@ static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) return IRQ_HANDLED; } -static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) -{ - struct mc13xxx_rtc *priv = dev; - struct mc13xxx *mc13xxx = priv->mc13xxx; - - rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); - - mc13xxx_irq_ack(mc13xxx, irq); - - return IRQ_HANDLED; -} - static const struct rtc_class_ops mc13xxx_rtc_ops = { .read_time = mc13xxx_rtc_read_time, .set_mmss64 = mc13xxx_rtc_set_mmss, @@ -307,11 +295,6 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev) if (ret) goto err_irq_request; - ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_1HZ, - mc13xxx_rtc_update_handler, DRIVER_NAME, priv); - if (ret) - goto err_irq_request; - ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); if (ret) @@ -326,7 +309,6 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev) err_irq_request: mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); - mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); mc13xxx_unlock(mc13xxx); @@ -341,7 +323,6 @@ static int mc13xxx_rtc_remove(struct platform_device *pdev) mc13xxx_lock(priv->mc13xxx); mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv); - mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv); mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv); mc13xxx_unlock(priv->mc13xxx); diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c new file mode 100644 index 000000000000..2f1772a358ca --- /dev/null +++ b/drivers/rtc/rtc-mc146818-lib.c @@ -0,0 +1,198 @@ +#include <linux/bcd.h> +#include <linux/delay.h> +#include <linux/export.h> +#include <linux/mc146818rtc.h> + +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#endif + +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char mc146818_is_updating(void) +{ + unsigned char uip; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + spin_unlock_irqrestore(&rtc_lock, flags); + return uip; +} + +unsigned int mc146818_get_time(struct rtc_time *time) +{ + unsigned char ctrl; + unsigned long flags; + unsigned char century = 0; + +#ifdef CONFIG_MACH_DECSTATION + unsigned int real_year; +#endif + + /* + * read RTC once any update in progress is done. The update + * can take just over 2ms. We wait 20ms. There is no need to + * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. + * If you need to know *exactly* when a second has started, enable + * periodic update complete interrupts, (via ioctl) and then + * immediately read /dev/rtc which will block until you get the IRQ. + * Once the read clears, read the RTC time (again via ioctl). Easy. + */ + if (mc146818_is_updating()) + mdelay(20); + + /* + * Only the values that we read from the RTC are set. We leave + * tm_wday, tm_yday and tm_isdst untouched. Even though the + * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated + * by the RTC when initially set to a non-zero value. + */ + spin_lock_irqsave(&rtc_lock, flags); + time->tm_sec = CMOS_READ(RTC_SECONDS); + time->tm_min = CMOS_READ(RTC_MINUTES); + time->tm_hour = CMOS_READ(RTC_HOURS); + time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); + time->tm_mon = CMOS_READ(RTC_MONTH); + time->tm_year = CMOS_READ(RTC_YEAR); +#ifdef CONFIG_MACH_DECSTATION + real_year = CMOS_READ(RTC_DEC_YEAR); +#endif +#ifdef CONFIG_ACPI + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) + century = CMOS_READ(acpi_gbl_FADT.century); +#endif + ctrl = CMOS_READ(RTC_CONTROL); + spin_unlock_irqrestore(&rtc_lock, flags); + + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + { + time->tm_sec = bcd2bin(time->tm_sec); + time->tm_min = bcd2bin(time->tm_min); + time->tm_hour = bcd2bin(time->tm_hour); + time->tm_mday = bcd2bin(time->tm_mday); + time->tm_mon = bcd2bin(time->tm_mon); + time->tm_year = bcd2bin(time->tm_year); + century = bcd2bin(century); + } + +#ifdef CONFIG_MACH_DECSTATION + time->tm_year += real_year - 72; +#endif + + if (century) + time->tm_year += (century - 19) * 100; + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if (time->tm_year <= 69) + time->tm_year += 100; + + time->tm_mon--; + + return RTC_24H; +} +EXPORT_SYMBOL_GPL(mc146818_get_time); + +/* Set the current date and time in the real time clock. */ +int mc146818_set_time(struct rtc_time *time) +{ + unsigned long flags; + unsigned char mon, day, hrs, min, sec; + unsigned char save_control, save_freq_select; + unsigned int yrs; +#ifdef CONFIG_MACH_DECSTATION + unsigned int real_yrs, leap_yr; +#endif + unsigned char century = 0; + + yrs = time->tm_year; + mon = time->tm_mon + 1; /* tm_mon starts at zero */ + day = time->tm_mday; + hrs = time->tm_hour; + min = time->tm_min; + sec = time->tm_sec; + + if (yrs > 255) /* They are unsigned */ + return -EINVAL; + + spin_lock_irqsave(&rtc_lock, flags); +#ifdef CONFIG_MACH_DECSTATION + real_yrs = yrs; + leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || + !((yrs + 1900) % 400)); + yrs = 72; + + /* + * We want to keep the year set to 73 until March + * for non-leap years, so that Feb, 29th is handled + * correctly. + */ + if (!leap_yr && mon < 3) { + real_yrs--; + yrs = 73; + } +#endif + +#ifdef CONFIG_ACPI + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) { + century = (yrs + 1900) / 100; + yrs %= 100; + } +#endif + + /* These limits and adjustments are independent of + * whether the chip is in binary mode or not. + */ + if (yrs > 169) { + spin_unlock_irqrestore(&rtc_lock, flags); + return -EINVAL; + } + + if (yrs >= 100) + yrs -= 100; + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) + || RTC_ALWAYS_BCD) { + sec = bin2bcd(sec); + min = bin2bcd(min); + hrs = bin2bcd(hrs); + day = bin2bcd(day); + mon = bin2bcd(mon); + yrs = bin2bcd(yrs); + century = bin2bcd(century); + } + + save_control = CMOS_READ(RTC_CONTROL); + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + +#ifdef CONFIG_MACH_DECSTATION + CMOS_WRITE(real_yrs, RTC_DEC_YEAR); +#endif + CMOS_WRITE(yrs, RTC_YEAR); + CMOS_WRITE(mon, RTC_MONTH); + CMOS_WRITE(day, RTC_DAY_OF_MONTH); + CMOS_WRITE(hrs, RTC_HOURS); + CMOS_WRITE(min, RTC_MINUTES); + CMOS_WRITE(sec, RTC_SECONDS); +#ifdef CONFIG_ACPI + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) + CMOS_WRITE(century, acpi_gbl_FADT.century); +#endif + + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + spin_unlock_irqrestore(&rtc_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(mc146818_set_time); diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 548ea6f6f384..7334c44fa7c3 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -32,11 +32,11 @@ #include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/kernel.h> +#include <linux/mc146818rtc.h> #include <linux/module.h> #include <linux/init.h> #include <linux/sfi.h> -#include <asm-generic/rtc.h> #include <asm/intel_scu_ipc.h> #include <asm/intel-mid.h> #include <asm/intel_mid_vrtc.h> @@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) if (mrst->irq <= 0) return -EIO; - /* Basic alarms only support hour, minute, and seconds fields. - * Some also support day and month, for alarms up to a year in - * the future. - */ - t->time.tm_mday = -1; - t->time.tm_mon = -1; - t->time.tm_year = -1; - /* vRTC only supports binary mode */ spin_lock_irq(&rtc_lock); t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); @@ -266,7 +258,7 @@ static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) } -#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) +#if IS_ENABLED(CONFIG_RTC_INTF_PROC) static int mrst_procfs(struct device *dev, struct seq_file *seq) { diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 7bd89d90048f..359876a88ac8 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -240,9 +240,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) mxc_rtc_irq_enable(&pdev->dev, RTC_ALM_BIT, 0); } - if (status & RTC_1HZ_BIT) - events |= (RTC_UF | RTC_IRQF); - if (status & PIT_ALL_ON) events |= (RTC_PF | RTC_IRQF); diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c index 9c18d6fd8107..ea20f627dabe 100644 --- a/drivers/rtc/rtc-opal.c +++ b/drivers/rtc/rtc-opal.c @@ -134,7 +134,7 @@ static int opal_get_tpo_time(struct device *dev, struct rtc_wkalrm *alarm) goto exit; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) { rc = -EIO; goto exit; @@ -181,7 +181,7 @@ static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm) goto exit; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) rc = -EIO; diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index da27738b1242..b4478cc92b55 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -46,8 +46,6 @@ #include <linux/module.h> #include <linux/sysfs.h> -#define DRV_VERSION "0.6" - /* REGISTERS */ #define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ #define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */ @@ -98,7 +96,7 @@ #define CD_TMR_TE BIT(3) /* Countdown timer enable */ /* PCF2123_REG_OFFSET BITS */ -#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */ +#define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ #define OFFSET_COARSE BIT(7) /* Coarse mode offset */ #define OFFSET_STEP (2170) /* Offset step in parts per billion */ @@ -219,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset) if (reg & OFFSET_COARSE) reg <<= 1; /* multiply by 2 and sign extend */ else - reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */ + reg = sign_extend32(reg, OFFSET_SIGN_BIT); *offset = ((long)reg) * OFFSET_STEP; @@ -395,7 +393,6 @@ static int pcf2123_probe(struct spi_device *spi) } } - dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n"); dev_info(&spi->dev, "spiclk %u KHz.\n", (spi->max_speed_hz + 500) / 1000); @@ -474,4 +471,3 @@ module_spi_driver(pcf2123_driver); MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>"); MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index e8ddbb359d11..efb0a08ac117 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -16,6 +16,16 @@ #include <linux/rtc.h> #include <linux/module.h> +/* + * Information for this driver was pulled from the following datasheets. + * + * http://www.nxp.com/documents/data_sheet/PCF85063A.pdf + * http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf + * + * PCF85063A -- Rev. 6 — 18 November 2015 + * PCF85063TP -- Rev. 4 — 6 May 2015 +*/ + #define PCF85063_REG_CTRL1 0x00 /* status */ #define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL2 0x01 @@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1) return 0; } -/* - * In the routines that deal directly with the pcf85063 hardware, we use - * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. - */ +static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1) +{ + s32 ret; + + /* start the clock */ + ctrl1 &= PCF85063_REG_CTRL1_STOP; + + ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); + if (ret < 0) { + dev_err(&client->dev, "Failing to start the clock\n"); + return -EIO; + } + + return 0; +} + static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) { int rc; @@ -90,8 +112,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_wday = regs[4] & 0x07; tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */ tm->tm_year = bcd2bin(regs[6]); - if (tm->tm_year < 70) - tm->tm_year += 100; /* assume we are in 1970...2069 */ + tm->tm_year += 100; return rtc_valid_tm(tm); } @@ -99,13 +120,17 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) { int rc; - u8 regs[8]; + u8 regs[7]; + u8 ctrl1; + + if ((tm->tm_year < 100) || (tm->tm_year > 199)) + return -EINVAL; /* * to accurately set the time, reset the divider chain and keep it in * reset state until all time/date registers are written */ - rc = pcf85063_stop_clock(client, ®s[7]); + rc = pcf85063_stop_clock(client, &ctrl1); if (rc != 0) return rc; @@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) regs[5] = bin2bcd(tm->tm_mon + 1); /* year and century */ - regs[6] = bin2bcd(tm->tm_year % 100); - - /* - * after all time/date registers are written, let the 'address auto - * increment' feature wrap around and write register CTRL1 to re-enable - * the clock divider chain again - */ - regs[7] &= ~PCF85063_REG_CTRL1_STOP; + regs[6] = bin2bcd(tm->tm_year - 100); /* write all registers at once */ rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC, @@ -142,6 +160,15 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) return rc; } + /* + * Write the control register as a separate action since the size of + * the register space is different between the PCF85063TP and + * PCF85063A devices. The rollover point can not be used. + */ + rc = pcf85063_start_clock(client, ctrl1); + if (rc != 0) + return rc; + return 0; } diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index c8f95b8e463a..1227ceab61ee 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -23,8 +23,6 @@ #include <linux/of.h> #include <linux/err.h> -#define DRV_VERSION "0.4.4" - #define PCF8563_REG_ST1 0x00 /* status */ #define PCF8563_REG_ST2 0x01 #define PCF8563_BIT_AIE (1 << 1) @@ -343,14 +341,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n", __func__, buf[0], buf[1], buf[2], buf[3]); + tm->time.tm_sec = 0; tm->time.tm_min = bcd2bin(buf[0] & 0x7F); tm->time.tm_hour = bcd2bin(buf[1] & 0x3F); tm->time.tm_mday = bcd2bin(buf[2] & 0x3F); tm->time.tm_wday = bcd2bin(buf[3] & 0x7); - tm->time.tm_mon = -1; - tm->time.tm_year = -1; - tm->time.tm_yday = -1; - tm->time.tm_isdst = -1; err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending); if (err < 0) @@ -535,7 +530,7 @@ static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563) init.name = "pcf8563-clkout"; init.ops = &pcf8563_clkout_ops; - init.flags = CLK_IS_ROOT; + init.flags = 0; init.parent_names = NULL; init.num_parents = 0; pcf8563->clkout_hw.init = &init; @@ -580,8 +575,6 @@ static int pcf8563_probe(struct i2c_client *client, if (!pcf8563) return -ENOMEM; - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - i2c_set_clientdata(client, pcf8563); pcf8563->client = client; device_set_wakeup_capable(&client->dev, 1); @@ -662,4 +655,3 @@ module_i2c_driver(pcf8563_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c index f28d57788951..68ce77414bdc 100644 --- a/drivers/rtc/rtc-rc5t583.c +++ b/drivers/rtc/rtc-rc5t583.c @@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) return ret; } + alm->time.tm_sec = 0; alm->time.tm_min = bcd2bin(alarm_data[0]); alm->time.tm_hour = bcd2bin(alarm_data[1]); alm->time.tm_mday = bcd2bin(alarm_data[2]); diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index 5f48167c802a..89f38e3e917d 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c @@ -50,7 +50,6 @@ #include <linux/io.h> #define DRV_NAME "rs5c313" -#define DRV_VERSION "1.13" #ifdef CONFIG_SH_LANDISK /*****************************************************/ @@ -407,7 +406,6 @@ static void __exit rs5c313_rtc_exit(void) module_init(rs5c313_rtc_init); module_exit(rs5c313_rtc_exit); -MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>"); MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 1162fecab8cf..9a306983aaba 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -25,8 +25,6 @@ #include <linux/spi/spi.h> #include <linux/module.h> -#define DRV_VERSION "0.2" - #define RS5C348_REG_SECS 0 #define RS5C348_REG_MINS 1 #define RS5C348_REG_HOURS 2 @@ -171,7 +169,6 @@ static int rs5c348_probe(struct spi_device *spi) goto kfree_exit; } - dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n"); dev_info(&spi->dev, "spiclk %u KHz.\n", (spi->max_speed_hz + 500) / 1000); @@ -230,5 +227,4 @@ module_spi_driver(rs5c348_driver); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("spi:rtc-rs5c348"); diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 28871cd7e3b5..c8c757466783 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -16,9 +16,6 @@ #include <linux/slab.h> #include <linux/module.h> -#define DRV_VERSION "0.6" - - /* * Ricoh has a family of I2C based RTCs, which differ only slightly from * each other. Differences center on pinout (e.g. how many interrupts, @@ -240,11 +237,11 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) +#if IS_ENABLED(CONFIG_RTC_INTF_PROC) #define NEED_TRIM #endif -#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) +#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS) #define NEED_TRIM #endif @@ -344,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->time.tm_sec = 0; t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]); - t->time.tm_mday = -1; - t->time.tm_mon = -1; - t->time.tm_year = -1; - t->time.tm_wday = -1; - t->time.tm_yday = -1; - t->time.tm_isdst = -1; /* ... and status */ t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE); @@ -412,7 +403,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) return 0; } -#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) +#if IS_ENABLED(CONFIG_RTC_INTF_PROC) static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq) { @@ -441,7 +432,7 @@ static const struct rtc_class_ops rs5c372_rtc_ops = { .alarm_irq_enable = rs5c_rtc_alarm_irq_enable, }; -#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) +#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS) static ssize_t rs5c372_sysfs_show_trim(struct device *dev, struct device_attribute *attr, char *buf) @@ -509,9 +500,9 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) int addr, i, ret = 0; if (rs5c372->type == rtc_r2025sd) { - if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST)) + if (rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST) return ret; - rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST; + rs5c372->regs[RS5C_REG_CTRL2] |= R2025_CTRL2_XST; } else { if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP)) return ret; @@ -640,7 +631,7 @@ static int rs5c372_probe(struct i2c_client *client, if (rs5c372_get_datetime(client, &tm) < 0) dev_warn(&client->dev, "clock needs to be set\n"); - dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", + dev_info(&client->dev, "%s found, %s\n", ({ char *s; switch (rs5c372->type) { case rtc_r2025sd: s = "r2025sd"; break; case rtc_r2221tl: s = "r2221tl"; break; @@ -696,4 +687,3 @@ MODULE_AUTHOR( "Paul Mundt <lethal@linux-sh.org>"); MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index d0cbf08040cd..1f9f7b4bf3fb 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -1,5 +1,5 @@ /* - * Micro Crystal RV-3029 rtc class driver + * Micro Crystal RV-3029 / RV-3049 rtc class driver * * Author: Gregory Hermant <gregory.hermant@calao-systems.com> * Michael Buesch <m@bues.ch> @@ -14,13 +14,14 @@ #include <linux/module.h> #include <linux/i2c.h> +#include <linux/spi/spi.h> #include <linux/bcd.h> #include <linux/rtc.h> #include <linux/delay.h> #include <linux/of.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> - +#include <linux/regmap.h> /* Register map */ /* control section */ @@ -75,6 +76,7 @@ #define RV3029_A_DW 0x14 #define RV3029_A_MO 0x15 #define RV3029_A_YR 0x16 +#define RV3029_A_AE_X BIT(7) #define RV3029_ALARM_SECTION_LEN 0x07 /* timer section */ @@ -116,85 +118,84 @@ #define RV3029_USR2_RAM_PAGE 0x3C #define RV3029_USR2_SECTION_LEN 0x04 -static int -rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf, - unsigned len) +struct rv3029_data { + struct device *dev; + struct rtc_device *rtc; + struct regmap *regmap; + int irq; +}; + +static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf, + unsigned int len) { - int ret; + struct rv3029_data *rv3029 = dev_get_drvdata(dev); if ((reg > RV3029_USR1_RAM_PAGE + 7) || - (reg + len > RV3029_USR1_RAM_PAGE + 8)) + (reg + len > RV3029_USR1_RAM_PAGE + 8)) return -EINVAL; - ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf); - if (ret < 0) - return ret; - if (ret < len) - return -EIO; - return 0; + return regmap_bulk_read(rv3029->regmap, reg, buf, len); } -static int -rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[], - unsigned len) +static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[], + unsigned int len) { + struct rv3029_data *rv3029 = dev_get_drvdata(dev); + if ((reg > RV3029_USR1_RAM_PAGE + 7) || - (reg + len > RV3029_USR1_RAM_PAGE + 8)) + (reg + len > RV3029_USR1_RAM_PAGE + 8)) return -EINVAL; - return i2c_smbus_write_i2c_block_data(client, reg, len, buf); + return regmap_bulk_write(rv3029->regmap, reg, buf, len); } -static int -rv3029_i2c_update_bits(struct i2c_client *client, u8 reg, u8 mask, u8 set) +static int rv3029_update_bits(struct device *dev, u8 reg, u8 mask, u8 set) { u8 buf; int ret; - ret = rv3029_i2c_read_regs(client, reg, &buf, 1); + ret = rv3029_read_regs(dev, reg, &buf, 1); if (ret < 0) return ret; buf &= ~mask; buf |= set & mask; - ret = rv3029_i2c_write_regs(client, reg, &buf, 1); + ret = rv3029_write_regs(dev, reg, &buf, 1); if (ret < 0) return ret; return 0; } -static int -rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf) +static int rv3029_get_sr(struct device *dev, u8 *buf) { - int ret = rv3029_i2c_read_regs(client, RV3029_STATUS, buf, 1); + int ret = rv3029_read_regs(dev, RV3029_STATUS, buf, 1); if (ret < 0) return -EIO; - dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); + dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); return 0; } -static int -rv3029_i2c_set_sr(struct i2c_client *client, u8 val) +static int rv3029_set_sr(struct device *dev, u8 val) { u8 buf[1]; int sr; buf[0] = val; - sr = rv3029_i2c_write_regs(client, RV3029_STATUS, buf, 1); - dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); + sr = rv3029_write_regs(dev, RV3029_STATUS, buf, 1); + dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); if (sr < 0) return -EIO; return 0; } -static int rv3029_eeprom_busywait(struct i2c_client *client) +static int rv3029_eeprom_busywait(struct device *dev) { int i, ret; u8 sr; for (i = 100; i > 0; i--) { - ret = rv3029_i2c_get_sr(client, &sr); + ret = rv3029_get_sr(dev, &sr); if (ret < 0) break; if (!(sr & RV3029_STATUS_EEBUSY)) @@ -202,28 +203,28 @@ static int rv3029_eeprom_busywait(struct i2c_client *client) usleep_range(1000, 10000); } if (i <= 0) { - dev_err(&client->dev, "EEPROM busy wait timeout.\n"); + dev_err(dev, "EEPROM busy wait timeout.\n"); return -ETIMEDOUT; } return ret; } -static int rv3029_eeprom_exit(struct i2c_client *client) +static int rv3029_eeprom_exit(struct device *dev) { /* Re-enable eeprom refresh */ - return rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL, - RV3029_ONOFF_CTRL_EERE, - RV3029_ONOFF_CTRL_EERE); + return rv3029_update_bits(dev, RV3029_ONOFF_CTRL, + RV3029_ONOFF_CTRL_EERE, + RV3029_ONOFF_CTRL_EERE); } -static int rv3029_eeprom_enter(struct i2c_client *client) +static int rv3029_eeprom_enter(struct device *dev) { int ret; u8 sr; /* Check whether we are in the allowed voltage range. */ - ret = rv3029_i2c_get_sr(client, &sr); + ret = rv3029_get_sr(dev, &sr); if (ret < 0) return ret; if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) { @@ -232,129 +233,168 @@ static int rv3029_eeprom_enter(struct i2c_client *client) */ sr &= ~RV3029_STATUS_VLOW1; sr &= ~RV3029_STATUS_VLOW2; - ret = rv3029_i2c_set_sr(client, sr); + ret = rv3029_set_sr(dev, sr); if (ret < 0) return ret; usleep_range(1000, 10000); - ret = rv3029_i2c_get_sr(client, &sr); + ret = rv3029_get_sr(dev, &sr); if (ret < 0) return ret; if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) { - dev_err(&client->dev, + dev_err(dev, "Supply voltage is too low to safely access the EEPROM.\n"); return -ENODEV; } } /* Disable eeprom refresh. */ - ret = rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL, - RV3029_ONOFF_CTRL_EERE, 0); + ret = rv3029_update_bits(dev, RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE, + 0); if (ret < 0) return ret; /* Wait for any previous eeprom accesses to finish. */ - ret = rv3029_eeprom_busywait(client); + ret = rv3029_eeprom_busywait(dev); if (ret < 0) - rv3029_eeprom_exit(client); + rv3029_eeprom_exit(dev); return ret; } -static int rv3029_eeprom_read(struct i2c_client *client, u8 reg, +static int rv3029_eeprom_read(struct device *dev, u8 reg, u8 buf[], size_t len) { int ret, err; - err = rv3029_eeprom_enter(client); + err = rv3029_eeprom_enter(dev); if (err < 0) return err; - ret = rv3029_i2c_read_regs(client, reg, buf, len); + ret = rv3029_read_regs(dev, reg, buf, len); - err = rv3029_eeprom_exit(client); + err = rv3029_eeprom_exit(dev); if (err < 0) return err; return ret; } -static int rv3029_eeprom_write(struct i2c_client *client, u8 reg, +static int rv3029_eeprom_write(struct device *dev, u8 reg, u8 const buf[], size_t len) { int ret, err; size_t i; u8 tmp; - err = rv3029_eeprom_enter(client); + err = rv3029_eeprom_enter(dev); if (err < 0) return err; for (i = 0; i < len; i++, reg++) { - ret = rv3029_i2c_read_regs(client, reg, &tmp, 1); + ret = rv3029_read_regs(dev, reg, &tmp, 1); if (ret < 0) break; if (tmp != buf[i]) { - ret = rv3029_i2c_write_regs(client, reg, &buf[i], 1); + ret = rv3029_write_regs(dev, reg, &buf[i], 1); if (ret < 0) break; } - ret = rv3029_eeprom_busywait(client); + ret = rv3029_eeprom_busywait(dev); if (ret < 0) break; } - err = rv3029_eeprom_exit(client); + err = rv3029_eeprom_exit(dev); if (err < 0) return err; return ret; } -static int rv3029_eeprom_update_bits(struct i2c_client *client, +static int rv3029_eeprom_update_bits(struct device *dev, u8 reg, u8 mask, u8 set) { u8 buf; int ret; - ret = rv3029_eeprom_read(client, reg, &buf, 1); + ret = rv3029_eeprom_read(dev, reg, &buf, 1); if (ret < 0) return ret; buf &= ~mask; buf |= set & mask; - ret = rv3029_eeprom_write(client, reg, &buf, 1); + ret = rv3029_eeprom_write(dev, reg, &buf, 1); if (ret < 0) return ret; return 0; } -static int -rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) +static irqreturn_t rv3029_handle_irq(int irq, void *dev_id) +{ + struct device *dev = dev_id; + struct rv3029_data *rv3029 = dev_get_drvdata(dev); + struct mutex *lock = &rv3029->rtc->ops_lock; + unsigned long events = 0; + u8 flags, controls; + int ret; + + mutex_lock(lock); + + ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1); + if (ret) { + dev_warn(dev, "Read IRQ Control Register error %d\n", ret); + mutex_unlock(lock); + return IRQ_NONE; + } + + ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1); + if (ret) { + dev_warn(dev, "Read IRQ Flags Register error %d\n", ret); + mutex_unlock(lock); + return IRQ_NONE; + } + + if (flags & RV3029_IRQ_FLAGS_AF) { + flags &= ~RV3029_IRQ_FLAGS_AF; + controls &= ~RV3029_IRQ_CTRL_AIE; + events |= RTC_AF; + } + + if (events) { + rtc_update_irq(rv3029->rtc, 1, events); + rv3029_write_regs(dev, RV3029_IRQ_FLAGS, &flags, 1); + rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1); + } + mutex_unlock(lock); + + return IRQ_HANDLED; +} + +static int rv3029_read_time(struct device *dev, struct rtc_time *tm) { u8 buf[1]; int ret; u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, }; - ret = rv3029_i2c_get_sr(client, buf); + ret = rv3029_get_sr(dev, buf); if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); + dev_err(dev, "%s: reading SR failed\n", __func__); return -EIO; } - ret = rv3029_i2c_read_regs(client, RV3029_W_SEC, regs, - RV3029_WATCH_SECTION_LEN); + ret = rv3029_read_regs(dev, RV3029_W_SEC, regs, + RV3029_WATCH_SECTION_LEN); if (ret < 0) { - dev_err(&client->dev, "%s: reading RTC section failed\n", - __func__); + dev_err(dev, "%s: reading RTC section failed\n", __func__); return ret; } - tm->tm_sec = bcd2bin(regs[RV3029_W_SEC-RV3029_W_SEC]); - tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES-RV3029_W_SEC]); + tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]); + tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]); /* HR field has a more complex interpretation */ { - const u8 _hr = regs[RV3029_W_HOURS-RV3029_W_SEC]; + const u8 _hr = regs[RV3029_W_HOURS - RV3029_W_SEC]; if (_hr & RV3029_REG_HR_12_24) { /* 12h format */ @@ -365,77 +405,86 @@ rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) tm->tm_hour = bcd2bin(_hr & 0x3f); } - tm->tm_mday = bcd2bin(regs[RV3029_W_DATE-RV3029_W_SEC]); - tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS-RV3029_W_SEC]) - 1; - tm->tm_year = bcd2bin(regs[RV3029_W_YEARS-RV3029_W_SEC]) + 100; - tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS-RV3029_W_SEC]) - 1; + tm->tm_mday = bcd2bin(regs[RV3029_W_DATE - RV3029_W_SEC]); + tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS - RV3029_W_SEC]) - 1; + tm->tm_year = bcd2bin(regs[RV3029_W_YEARS - RV3029_W_SEC]) + 100; + tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS - RV3029_W_SEC]) - 1; return 0; } -static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return rv3029_i2c_read_time(to_i2c_client(dev), tm); -} - -static int -rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm) +static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct rtc_time *const tm = &alarm->time; int ret; - u8 regs[8]; + u8 regs[8], controls, flags; - ret = rv3029_i2c_get_sr(client, regs); + ret = rv3029_get_sr(dev, regs); if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); + dev_err(dev, "%s: reading SR failed\n", __func__); return -EIO; } - ret = rv3029_i2c_read_regs(client, RV3029_A_SC, regs, - RV3029_ALARM_SECTION_LEN); + ret = rv3029_read_regs(dev, RV3029_A_SC, regs, + RV3029_ALARM_SECTION_LEN); if (ret < 0) { - dev_err(&client->dev, "%s: reading alarm section failed\n", - __func__); + dev_err(dev, "%s: reading alarm section failed\n", __func__); return ret; } - tm->tm_sec = bcd2bin(regs[RV3029_A_SC-RV3029_A_SC] & 0x7f); - tm->tm_min = bcd2bin(regs[RV3029_A_MN-RV3029_A_SC] & 0x7f); - tm->tm_hour = bcd2bin(regs[RV3029_A_HR-RV3029_A_SC] & 0x3f); - tm->tm_mday = bcd2bin(regs[RV3029_A_DT-RV3029_A_SC] & 0x3f); - tm->tm_mon = bcd2bin(regs[RV3029_A_MO-RV3029_A_SC] & 0x1f) - 1; - tm->tm_year = bcd2bin(regs[RV3029_A_YR-RV3029_A_SC] & 0x7f) + 100; - tm->tm_wday = bcd2bin(regs[RV3029_A_DW-RV3029_A_SC] & 0x07) - 1; + ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1); + if (ret) { + dev_err(dev, "Read IRQ Control Register error %d\n", ret); + return ret; + } + ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1); + if (ret < 0) { + dev_err(dev, "Read IRQ Flags Register error %d\n", ret); + return ret; + } - return 0; -} + tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f); + tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f); + tm->tm_hour = bcd2bin(regs[RV3029_A_HR - RV3029_A_SC] & 0x3f); + tm->tm_mday = bcd2bin(regs[RV3029_A_DT - RV3029_A_SC] & 0x3f); + tm->tm_mon = bcd2bin(regs[RV3029_A_MO - RV3029_A_SC] & 0x1f) - 1; + tm->tm_year = bcd2bin(regs[RV3029_A_YR - RV3029_A_SC] & 0x7f) + 100; + tm->tm_wday = bcd2bin(regs[RV3029_A_DW - RV3029_A_SC] & 0x07) - 1; -static int -rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - return rv3029_i2c_read_alarm(to_i2c_client(dev), alarm); + alarm->enabled = !!(controls & RV3029_IRQ_CTRL_AIE); + alarm->pending = (flags & RV3029_IRQ_FLAGS_AF) && alarm->enabled; + + return 0; } -static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client, - int enable) +static int rv3029_alarm_irq_enable(struct device *dev, unsigned int enable) { int ret; + u8 controls; + + ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1); + if (ret < 0) { + dev_warn(dev, "Read IRQ Control Register error %d\n", ret); + return ret; + } /* enable/disable AIE irq */ - ret = rv3029_i2c_update_bits(client, RV3029_IRQ_CTRL, - RV3029_IRQ_CTRL_AIE, - (enable ? RV3029_IRQ_CTRL_AIE : 0)); + if (enable) + controls |= RV3029_IRQ_CTRL_AIE; + else + controls &= ~RV3029_IRQ_CTRL_AIE; + + ret = rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1); if (ret < 0) { - dev_err(&client->dev, "can't update INT reg\n"); + dev_err(dev, "can't update INT reg\n"); return ret; } return 0; } -static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client, - struct rtc_wkalrm *alarm) +static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct rtc_time *const tm = &alarm->time; int ret; @@ -449,57 +498,48 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client, if (tm->tm_year < 100) return -EINVAL; - ret = rv3029_i2c_get_sr(client, regs); + ret = rv3029_get_sr(dev, regs); if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); + dev_err(dev, "%s: reading SR failed\n", __func__); return -EIO; } - regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f); - regs[RV3029_A_MN-RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f); - regs[RV3029_A_HR-RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f); - regs[RV3029_A_DT-RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f); - regs[RV3029_A_MO-RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1); - regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1); - regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100); - ret = rv3029_i2c_write_regs(client, RV3029_A_SC, regs, - RV3029_ALARM_SECTION_LEN); + /* Activate all the alarms with AE_x bit */ + regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec) | RV3029_A_AE_X; + regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min) | RV3029_A_AE_X; + regs[RV3029_A_HR - RV3029_A_SC] = (bin2bcd(tm->tm_hour) & 0x3f) + | RV3029_A_AE_X; + regs[RV3029_A_DT - RV3029_A_SC] = (bin2bcd(tm->tm_mday) & 0x3f) + | RV3029_A_AE_X; + regs[RV3029_A_MO - RV3029_A_SC] = (bin2bcd(tm->tm_mon + 1) & 0x1f) + | RV3029_A_AE_X; + regs[RV3029_A_DW - RV3029_A_SC] = (bin2bcd(tm->tm_wday + 1) & 0x7) + | RV3029_A_AE_X; + regs[RV3029_A_YR - RV3029_A_SC] = (bin2bcd(tm->tm_year - 100)) + | RV3029_A_AE_X; + + /* Write the alarm */ + ret = rv3029_write_regs(dev, RV3029_A_SC, regs, + RV3029_ALARM_SECTION_LEN); if (ret < 0) return ret; if (alarm->enabled) { - /* clear AF flag */ - ret = rv3029_i2c_update_bits(client, RV3029_IRQ_FLAGS, - RV3029_IRQ_FLAGS_AF, 0); - if (ret < 0) { - dev_err(&client->dev, "can't clear alarm flag\n"); - return ret; - } /* enable AIE irq */ - ret = rv3029_rtc_i2c_alarm_set_irq(client, 1); + ret = rv3029_alarm_irq_enable(dev, 1); if (ret) return ret; - - dev_dbg(&client->dev, "alarm IRQ armed\n"); } else { /* disable AIE irq */ - ret = rv3029_rtc_i2c_alarm_set_irq(client, 0); + ret = rv3029_alarm_irq_enable(dev, 0); if (ret) return ret; - - dev_dbg(&client->dev, "alarm IRQ disabled\n"); } return 0; } -static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - return rv3029_rtc_i2c_set_alarm(to_i2c_client(dev), alarm); -} - -static int -rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) +static int rv3029_set_time(struct device *dev, struct rtc_time *tm) { u8 regs[8]; int ret; @@ -512,39 +552,34 @@ rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) if (tm->tm_year < 100) return -EINVAL; - regs[RV3029_W_SEC-RV3029_W_SEC] = bin2bcd(tm->tm_sec); - regs[RV3029_W_MINUTES-RV3029_W_SEC] = bin2bcd(tm->tm_min); - regs[RV3029_W_HOURS-RV3029_W_SEC] = bin2bcd(tm->tm_hour); - regs[RV3029_W_DATE-RV3029_W_SEC] = bin2bcd(tm->tm_mday); - regs[RV3029_W_MONTHS-RV3029_W_SEC] = bin2bcd(tm->tm_mon+1); - regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1); - regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100); + regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec); + regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min); + regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour); + regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday); + regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1); + regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd(tm->tm_wday + 1) & 0x7; + regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 100); - ret = rv3029_i2c_write_regs(client, RV3029_W_SEC, regs, - RV3029_WATCH_SECTION_LEN); + ret = rv3029_write_regs(dev, RV3029_W_SEC, regs, + RV3029_WATCH_SECTION_LEN); if (ret < 0) return ret; - ret = rv3029_i2c_get_sr(client, regs); + ret = rv3029_get_sr(dev, regs); if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); + dev_err(dev, "%s: reading SR failed\n", __func__); return ret; } /* clear PON bit */ - ret = rv3029_i2c_set_sr(client, (regs[0] & ~RV3029_STATUS_PON)); + ret = rv3029_set_sr(dev, (regs[0] & ~RV3029_STATUS_PON)); if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); + dev_err(dev, "%s: reading SR failed\n", __func__); return ret; } return 0; } -static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return rv3029_i2c_set_time(to_i2c_client(dev), tm); -} - static const struct rv3029_trickle_tab_elem { u32 r; /* resistance in ohms */ u8 conf; /* trickle config bits */ @@ -602,9 +637,9 @@ static const struct rv3029_trickle_tab_elem { }, }; -static void rv3029_trickle_config(struct i2c_client *client) +static void rv3029_trickle_config(struct device *dev) { - struct device_node *of_node = client->dev.of_node; + struct device_node *of_node = dev->of_node; const struct rv3029_trickle_tab_elem *elem; int i, err; u32 ohms; @@ -626,27 +661,25 @@ static void rv3029_trickle_config(struct i2c_client *client) break; } trickle_set_bits = elem->conf; - dev_info(&client->dev, + dev_info(dev, "Trickle charger enabled at %d ohms resistance.\n", elem->r); } - err = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL, + err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL, RV3029_TRICKLE_MASK, trickle_set_bits); - if (err < 0) { - dev_err(&client->dev, - "Failed to update trickle charger config\n"); - } + if (err < 0) + dev_err(dev, "Failed to update trickle charger config\n"); } #ifdef CONFIG_RTC_DRV_RV3029_HWMON -static int rv3029_read_temp(struct i2c_client *client, int *temp_mC) +static int rv3029_read_temp(struct device *dev, int *temp_mC) { int ret; u8 temp; - ret = rv3029_i2c_read_regs(client, RV3029_TEMP_PAGE, &temp, 1); + ret = rv3029_read_regs(dev, RV3029_TEMP_PAGE, &temp, 1); if (ret < 0) return ret; @@ -659,10 +692,9 @@ static ssize_t rv3029_hwmon_show_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = dev_get_drvdata(dev); int ret, temp_mC; - ret = rv3029_read_temp(client, &temp_mC); + ret = rv3029_read_temp(dev, &temp_mC); if (ret < 0) return ret; @@ -674,7 +706,6 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev, const char *buf, size_t count) { - struct i2c_client *client = dev_get_drvdata(dev); unsigned long interval_ms; int ret; u8 th_set_bits = 0; @@ -688,7 +719,7 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev, if (interval_ms >= 16000) th_set_bits |= RV3029_EECTRL_THP; } - ret = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL, + ret = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL, RV3029_EECTRL_THE | RV3029_EECTRL_THP, th_set_bits); if (ret < 0) @@ -701,11 +732,10 @@ static ssize_t rv3029_hwmon_show_update_interval(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = dev_get_drvdata(dev); int ret, interval_ms; u8 eectrl; - ret = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL, + ret = rv3029_eeprom_read(dev, RV3029_CONTROL_E2P_EECTRL, &eectrl, 1); if (ret < 0) return ret; @@ -735,82 +765,226 @@ static struct attribute *rv3029_hwmon_attrs[] = { }; ATTRIBUTE_GROUPS(rv3029_hwmon); -static void rv3029_hwmon_register(struct i2c_client *client) +static void rv3029_hwmon_register(struct device *dev, const char *name) { + struct rv3029_data *rv3029 = dev_get_drvdata(dev); struct device *hwmon_dev; - hwmon_dev = devm_hwmon_device_register_with_groups( - &client->dev, client->name, client, rv3029_hwmon_groups); + hwmon_dev = devm_hwmon_device_register_with_groups(dev, name, rv3029, + rv3029_hwmon_groups); if (IS_ERR(hwmon_dev)) { - dev_warn(&client->dev, - "unable to register hwmon device %ld\n", - PTR_ERR(hwmon_dev)); + dev_warn(dev, "unable to register hwmon device %ld\n", + PTR_ERR(hwmon_dev)); } } #else /* CONFIG_RTC_DRV_RV3029_HWMON */ -static void rv3029_hwmon_register(struct i2c_client *client) +static void rv3029_hwmon_register(struct device *dev, const char *name) { } #endif /* CONFIG_RTC_DRV_RV3029_HWMON */ -static const struct rtc_class_ops rv3029_rtc_ops = { - .read_time = rv3029_rtc_read_time, - .set_time = rv3029_rtc_set_time, - .read_alarm = rv3029_rtc_read_alarm, - .set_alarm = rv3029_rtc_set_alarm, +static struct rtc_class_ops rv3029_rtc_ops = { + .read_time = rv3029_read_time, + .set_time = rv3029_set_time, }; -static struct i2c_device_id rv3029_id[] = { - { "rv3029", 0 }, - { "rv3029c2", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, rv3029_id); - -static int rv3029_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name) { - struct rtc_device *rtc; + struct rv3029_data *rv3029; int rc = 0; u8 buf[1]; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL)) - return -ENODEV; + rv3029 = devm_kzalloc(dev, sizeof(*rv3029), GFP_KERNEL); + if (!rv3029) + return -ENOMEM; - rc = rv3029_i2c_get_sr(client, buf); + rv3029->regmap = regmap; + rv3029->irq = irq; + rv3029->dev = dev; + dev_set_drvdata(dev, rv3029); + + rc = rv3029_get_sr(dev, buf); if (rc < 0) { - dev_err(&client->dev, "reading status failed\n"); + dev_err(dev, "reading status failed\n"); return rc; } - rv3029_trickle_config(client); - rv3029_hwmon_register(client); - - rtc = devm_rtc_device_register(&client->dev, client->name, - &rv3029_rtc_ops, THIS_MODULE); + rv3029_trickle_config(dev); + rv3029_hwmon_register(dev, name); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); + rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops, + THIS_MODULE); + if (IS_ERR(rv3029->rtc)) { + dev_err(dev, "unable to register the class device\n"); + return PTR_ERR(rv3029->rtc); + } - i2c_set_clientdata(client, rtc); + if (rv3029->irq > 0) { + rc = devm_request_threaded_irq(dev, rv3029->irq, + NULL, rv3029_handle_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "rv3029", dev); + if (rc) { + dev_warn(dev, "unable to request IRQ, alarms disabled\n"); + rv3029->irq = 0; + } else { + rv3029_rtc_ops.read_alarm = rv3029_read_alarm; + rv3029_rtc_ops.set_alarm = rv3029_set_alarm; + rv3029_rtc_ops.alarm_irq_enable = rv3029_alarm_irq_enable; + } + } return 0; } +#if IS_ENABLED(CONFIG_I2C) + +static int rv3029_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + }; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK | + I2C_FUNC_SMBUS_BYTE)) { + dev_err(&client->dev, "Adapter does not support SMBUS_I2C_BLOCK or SMBUS_I2C_BYTE\n"); + return -ENODEV; + } + + regmap = devm_regmap_init_i2c(client, &config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "%s: regmap allocation failed: %ld\n", + __func__, PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return rv3029_probe(&client->dev, regmap, client->irq, client->name); +} + +static struct i2c_device_id rv3029_id[] = { + { "rv3029", 0 }, + { "rv3029c2", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rv3029_id); + static struct i2c_driver rv3029_driver = { .driver = { .name = "rtc-rv3029c2", }, - .probe = rv3029_probe, + .probe = rv3029_i2c_probe, .id_table = rv3029_id, }; -module_i2c_driver(rv3029_driver); +static int rv3029_register_driver(void) +{ + return i2c_add_driver(&rv3029_driver); +} + +static void rv3029_unregister_driver(void) +{ + i2c_del_driver(&rv3029_driver); +} + +#else + +static int rv3029_register_driver(void) +{ + return 0; +} + +static void rv3029_unregister_driver(void) +{ +} + +#endif + +#if IS_ENABLED(CONFIG_SPI_MASTER) + +static int rv3049_probe(struct spi_device *spi) +{ + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + }; + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n", + __func__, PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return rv3029_probe(&spi->dev, regmap, spi->irq, "rv3049"); +} + +static struct spi_driver rv3049_driver = { + .driver = { + .name = "rv3049", + }, + .probe = rv3049_probe, +}; + +static int rv3049_register_driver(void) +{ + return spi_register_driver(&rv3049_driver); +} + +static void rv3049_unregister_driver(void) +{ + spi_unregister_driver(&rv3049_driver); +} + +#else + +static int rv3049_register_driver(void) +{ + return 0; +} + +static void rv3049_unregister_driver(void) +{ +} + +#endif + +static int __init rv30x9_init(void) +{ + int ret; + + ret = rv3029_register_driver(); + if (ret) { + pr_err("Failed to register rv3029 driver: %d\n", ret); + return ret; + } + + ret = rv3049_register_driver(); + if (ret) { + pr_err("Failed to register rv3049 driver: %d\n", ret); + rv3029_unregister_driver(); + } + + return ret; +} +module_init(rv30x9_init) + +static void __exit rv30x9_exit(void) +{ + rv3049_unregister_driver(); + rv3029_unregister_driver(); +} +module_exit(rv30x9_exit) MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>"); MODULE_AUTHOR("Michael Buesch <m@bues.ch>"); -MODULE_DESCRIPTION("Micro Crystal RV3029 RTC driver"); +MODULE_DESCRIPTION("Micro Crystal RV3029/RV3049 RTC driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:rv3049"); diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index f623038e586e..9a2f6a95d5a7 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -13,12 +13,15 @@ #include <linux/bcd.h> #include <linux/bitops.h> +#include <linux/log2.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/rtc.h> +#define RV8803_I2C_TRY_COUNT 4 + #define RV8803_SEC 0x00 #define RV8803_MIN 0x01 #define RV8803_HOUR 0x02 @@ -56,19 +59,85 @@ struct rv8803_data { u8 ctrl; }; +static int rv8803_read_reg(const struct i2c_client *client, u8 reg) +{ + int try = RV8803_I2C_TRY_COUNT; + s32 ret; + + /* + * There is a 61µs window during which the RTC does not acknowledge I2C + * transfers. In that case, ensure that there are multiple attempts. + */ + do + ret = i2c_smbus_read_byte_data(client, reg); + while ((ret == -ENXIO || ret == -EIO) && --try); + if (ret < 0) + dev_err(&client->dev, "Unable to read register 0x%02x\n", reg); + + return ret; +} + +static int rv8803_read_regs(const struct i2c_client *client, + u8 reg, u8 count, u8 *values) +{ + int try = RV8803_I2C_TRY_COUNT; + s32 ret; + + do + ret = i2c_smbus_read_i2c_block_data(client, reg, count, values); + while ((ret == -ENXIO || ret == -EIO) && --try); + if (ret != count) { + dev_err(&client->dev, + "Unable to read registers 0x%02x..0x%02x\n", + reg, reg + count - 1); + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value) +{ + int try = RV8803_I2C_TRY_COUNT; + s32 ret; + + do + ret = i2c_smbus_write_byte_data(client, reg, value); + while ((ret == -ENXIO || ret == -EIO) && --try); + if (ret) + dev_err(&client->dev, "Unable to write register 0x%02x\n", reg); + + return ret; +} + +static int rv8803_write_regs(const struct i2c_client *client, + u8 reg, u8 count, const u8 *values) +{ + int try = RV8803_I2C_TRY_COUNT; + s32 ret; + + do + ret = i2c_smbus_write_i2c_block_data(client, reg, count, + values); + while ((ret == -ENXIO || ret == -EIO) && --try); + if (ret) + dev_err(&client->dev, + "Unable to write registers 0x%02x..0x%02x\n", + reg, reg + count - 1); + + return ret; +} + static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) { struct i2c_client *client = dev_id; struct rv8803_data *rv8803 = i2c_get_clientdata(client); unsigned long events = 0; - int flags, try = 0; + int flags; mutex_lock(&rv8803->flags_lock); - do { - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); - try++; - } while ((flags == -ENXIO) && (try < 3)); + flags = rv8803_read_reg(client, RV8803_FLAG); if (flags <= 0) { mutex_unlock(&rv8803->flags_lock); return IRQ_NONE; @@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) if (events) { rtc_update_irq(rv8803->rtc, 1, events); - i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); - i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, - rv8803->ctrl); + rv8803_write_reg(client, RV8803_FLAG, flags); + rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl); } mutex_unlock(&rv8803->flags_lock); @@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) u8 *date = date1; int ret, flags; - flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); + flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); if (flags < 0) return flags; @@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) return -EINVAL; } - ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, - 7, date); - if (ret != 7) - return ret < 0 ? ret : -EIO; + ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date); + if (ret) + return ret; if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) { - ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, - 7, date2); - if (ret != 7) - return ret < 0 ? ret : -EIO; + ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2); + if (ret) + return ret; if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59)) date = date2; @@ -145,23 +211,33 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) tm->tm_sec = bcd2bin(date[RV8803_SEC] & 0x7f); tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f); tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f); - tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f); + tm->tm_wday = ilog2(date[RV8803_WEEK] & 0x7f); tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f); tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1; tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100; - return rtc_valid_tm(tm); + return 0; } static int rv8803_set_time(struct device *dev, struct rtc_time *tm) { struct rv8803_data *rv8803 = dev_get_drvdata(dev); u8 date[7]; - int flags, ret; + int ctrl, flags, ret; if ((tm->tm_year < 100) || (tm->tm_year > 199)) return -EINVAL; + ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL); + if (ctrl < 0) + return ctrl; + + /* Stop the clock */ + ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, + ctrl | RV8803_CTRL_RESET); + if (ret) + return ret; + date[RV8803_SEC] = bin2bcd(tm->tm_sec); date[RV8803_MIN] = bin2bcd(tm->tm_min); date[RV8803_HOUR] = bin2bcd(tm->tm_hour); @@ -170,21 +246,26 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm) date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1); date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100); - ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC, - 7, date); - if (ret < 0) + ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date); + if (ret) + return ret; + + /* Restart the clock */ + ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, + ctrl & ~RV8803_CTRL_RESET); + if (ret) return ret; mutex_lock(&rv8803->flags_lock); - flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); + flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); if (flags < 0) { mutex_unlock(&rv8803->flags_lock); return flags; } - ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, - flags & ~RV8803_FLAG_V2F); + ret = rv8803_write_reg(rv8803->client, RV8803_FLAG, + flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F)); mutex_unlock(&rv8803->flags_lock); @@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) u8 alarmvals[3]; int flags, ret; - ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN, - 3, alarmvals); - if (ret != 3) - return ret < 0 ? ret : -EIO; + ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals); + if (ret) + return ret; - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + flags = rv8803_read_reg(client, RV8803_FLAG); if (flags < 0) return flags; alrm->time.tm_sec = 0; alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); - alrm->time.tm_wday = -1; alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f); - alrm->time.tm_mon = -1; - alrm->time.tm_year = -1; alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE); alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled; @@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) mutex_lock(&rv8803->flags_lock); - ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl); - if (ret != 2) { + ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl); + if (ret) { mutex_unlock(&rv8803->flags_lock); - return ret < 0 ? ret : -EIO; + return ret; } alarmvals[0] = bin2bcd(alrm->time.tm_min); @@ -251,8 +328,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) { rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE); - err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, - rv8803->ctrl); + err = rv8803_write_reg(rv8803->client, RV8803_CTRL, + rv8803->ctrl); if (err) { mutex_unlock(&rv8803->flags_lock); return err; @@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) } ctrl[1] &= ~RV8803_FLAG_AF; - err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]); + err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]); mutex_unlock(&rv8803->flags_lock); if (err) return err; - err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN, - 3, alarmvals); + err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals); if (err) return err; @@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (rv8803->rtc->aie_timer.enabled) rv8803->ctrl |= RV8803_CTRL_AIE; - err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, - rv8803->ctrl); + err = rv8803_write_reg(rv8803->client, RV8803_CTRL, + rv8803->ctrl); if (err) return err; } @@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled) } mutex_lock(&rv8803->flags_lock); - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + flags = rv8803_read_reg(client, RV8803_FLAG); if (flags < 0) { mutex_unlock(&rv8803->flags_lock); return flags; } flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF); - err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); + err = rv8803_write_reg(client, RV8803_FLAG, flags); mutex_unlock(&rv8803->flags_lock); if (err) return err; if (ctrl != rv8803->ctrl) { rv8803->ctrl = ctrl; - err = i2c_smbus_write_byte_data(client, RV8803_CTRL, - rv8803->ctrl); + err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl); if (err) return err; } @@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) switch (cmd) { case RTC_VL_READ: - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + flags = rv8803_read_reg(client, RV8803_FLAG); if (flags < 0) return flags; @@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) case RTC_VL_CLR: mutex_lock(&rv8803->flags_lock); - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + flags = rv8803_read_reg(client, RV8803_FLAG); if (flags < 0) { mutex_unlock(&rv8803->flags_lock); return flags; } flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F); - ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); + ret = rv8803_write_reg(client, RV8803_FLAG, flags); mutex_unlock(&rv8803->flags_lock); - if (ret < 0) + if (ret) return ret; return 0; @@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj, struct i2c_client *client = to_i2c_client(dev); int ret; - ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]); - if (ret < 0) + ret = rv8803_write_reg(client, RV8803_RAM, buf[0]); + if (ret) return ret; return 1; @@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj, struct i2c_client *client = to_i2c_client(dev); int ret; - ret = i2c_smbus_read_byte_data(client, RV8803_RAM); + ret = rv8803_read_reg(client, RV8803_RAM); if (ret < 0) return ret; @@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client, { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct rv8803_data *rv8803; - int err, flags, try = 0; + int err, flags; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { @@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client, rv8803->client = client; i2c_set_clientdata(client, rv8803); - /* - * There is a 60µs window where the RTC may not reply on the i2c bus in - * that case, the transfer is not ACKed. In that case, ensure there are - * multiple attempts. - */ - do { - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); - try++; - } while ((flags == -ENXIO) && (try < 3)); - + flags = rv8803_read_reg(client, RV8803_FLAG); if (flags < 0) return flags; @@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client, return PTR_ERR(rv8803->rtc); } - try = 0; - do { - err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT, - RV8803_EXT_WADA); - try++; - } while ((err == -ENXIO) && (try < 3)); + err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); if (err) return err; diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 772d221ec2d9..7163b91bb773 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -272,15 +272,9 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); - if (alarmvals[2] & RX8010_ALARM_AE) - t->time.tm_mday = -1; - else + if (!(alarmvals[2] & RX8010_ALARM_AE)) t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f); - t->time.tm_wday = -1; - t->time.tm_mon = -1; - t->time.tm_year = -1; - t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE); t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled; diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 9f105efbc546..2b85cc7a24e7 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -319,11 +319,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12 + (ald[1] & 0x20 ? 12 : 0); - t->time.tm_wday = -1; - t->time.tm_mday = -1; - t->time.tm_mon = -1; - t->time.tm_year = -1; - dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n", __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour, diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 161e25d016c3..0c362a3d1f17 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -18,8 +18,6 @@ #include <linux/rtc.h> #include <linux/log2.h> -#define DRV_VERSION "0.1" - #define RX8581_REG_SC 0x00 /* Second in BCD */ #define RX8581_REG_MN 0x01 /* Minute in BCD */ #define RX8581_REG_HR 0x02 /* Hour in BCD */ @@ -292,8 +290,6 @@ static int rx8581_probe(struct i2c_client *client, rx8581->write_block_data = rx8581_write_block_data; } - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rx8581->rtc = devm_rtc_device_register(&client->dev, rx8581_driver.driver.name, &rx8581_rtc_ops, THIS_MODULE); @@ -325,4 +321,3 @@ module_i2c_driver(rx8581_driver); MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index f40afdd0e5f5..5dab4665ca3b 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -15,6 +15,7 @@ #include <linux/bitrev.h> #include <linux/bcd.h> #include <linux/slab.h> +#include <linux/delay.h> #define S35390A_CMD_STATUS1 0 #define S35390A_CMD_STATUS2 1 @@ -34,10 +35,14 @@ #define S35390A_ALRM_BYTE_HOURS 1 #define S35390A_ALRM_BYTE_MINS 2 +/* flags for STATUS1 */ #define S35390A_FLAG_POC 0x01 #define S35390A_FLAG_BLD 0x02 +#define S35390A_FLAG_INT2 0x04 #define S35390A_FLAG_24H 0x40 #define S35390A_FLAG_RESET 0x80 + +/* flag for STATUS2 */ #define S35390A_FLAG_TEST 0x01 #define S35390A_INT2_MODE_MASK 0xF0 @@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) return 0; } -static int s35390a_reset(struct s35390a *s35390a) +/* + * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset. + * To keep the information if an irq is pending, pass the value read from + * STATUS1 to the caller. + */ +static int s35390a_reset(struct s35390a *s35390a, char *status1) { - char buf[1]; - - if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0) - return -EIO; - - if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD))) + char buf; + int ret; + unsigned initcount = 0; + + ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1); + if (ret < 0) + return ret; + + if (*status1 & S35390A_FLAG_POC) + /* + * Do not communicate for 0.5 seconds since the power-on + * detection circuit is in operation. + */ + msleep(500); + else if (!(*status1 & S35390A_FLAG_BLD)) + /* + * If both POC and BLD are unset everything is fine. + */ return 0; - buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H); - buf[0] &= 0xf0; - return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); + /* + * At least one of POC and BLD are set, so reinitialise chip. Keeping + * this information in the hardware to know later that the time isn't + * valid is unfortunately not possible because POC and BLD are cleared + * on read. So the reset is best done now. + * + * The 24H bit is kept over reset, so set it already here. + */ +initialize: + *status1 = S35390A_FLAG_24H; + buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; + ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); + + if (ret < 0) + return ret; + + ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); + if (ret < 0) + return ret; + + if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) { + /* Try up to five times to reset the chip */ + if (initcount < 5) { + ++initcount; + goto initialize; + } else + return -EIO; + } + + return 1; } static int s35390a_disable_test_mode(struct s35390a *s35390a) @@ -217,12 +266,12 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); - /* disable interrupt */ + /* disable interrupt (which deasserts the irq line) */ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); if (err < 0) return err; - /* clear pending interrupt, if any */ + /* clear pending interrupt (in STATUS1 only), if any */ err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); if (err < 0) return err; @@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) if (alm->time.tm_wday != -1) buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; + else + buf[S35390A_ALRM_BYTE_WDAY] = 0; buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, alm->time.tm_hour) | 0x80; @@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) if (err < 0) return err; - if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) - return -EINVAL; + if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { + /* + * When the alarm isn't enabled, the register to configure + * the alarm time isn't accessible. + */ + alm->enabled = 0; + return 0; + } else { + alm->enabled = 1; + } err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); if (err < 0) return err; /* This chip returns the bits of each byte in reverse order */ - for (i = 0; i < 3; ++i) { + for (i = 0; i < 3; ++i) buf[i] = bitrev8(buf[i]); - buf[i] &= ~0x80; - } - alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); - alm->time.tm_hour = s35390a_reg2hr(s35390a, - buf[S35390A_ALRM_BYTE_HOURS]); - alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); + /* + * B0 of the three matching registers is an enable flag. Iff it is set + * the configured value is used for matching. + */ + if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80) + alm->time.tm_wday = + bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80); + + if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80) + alm->time.tm_hour = + s35390a_reg2hr(s35390a, + buf[S35390A_ALRM_BYTE_HOURS] & ~0x80); + + if (buf[S35390A_ALRM_BYTE_MINS] & 0x80) + alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80); + + /* alarm triggers always at s=0 */ + alm->time.tm_sec = 0; dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", __func__, alm->time.tm_min, alm->time.tm_hour, @@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver; static int s35390a_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int err; + int err, err_reset; unsigned int i; struct s35390a *s35390a; struct rtc_time tm; - char buf[1]; + char buf, status1; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { err = -ENODEV; @@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client, } } - err = s35390a_reset(s35390a); - if (err < 0) { + err_reset = s35390a_reset(s35390a, &status1); + if (err_reset < 0) { + err = err_reset; dev_err(&client->dev, "error resetting chip\n"); goto exit_dummy; } - err = s35390a_disable_test_mode(s35390a); - if (err < 0) { - dev_err(&client->dev, "error disabling test mode\n"); - goto exit_dummy; - } - - err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); - if (err < 0) { - dev_err(&client->dev, "error checking 12/24 hour mode\n"); - goto exit_dummy; - } - if (buf[0] & S35390A_FLAG_24H) + if (status1 & S35390A_FLAG_24H) s35390a->twentyfourhour = 1; else s35390a->twentyfourhour = 0; - if (s35390a_get_datetime(client, &tm) < 0) + if (status1 & S35390A_FLAG_INT2) { + /* disable alarm (and maybe test mode) */ + buf = 0; + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1); + if (err < 0) { + dev_err(&client->dev, "error disabling alarm"); + goto exit_dummy; + } + } else { + err = s35390a_disable_test_mode(s35390a); + if (err < 0) { + dev_err(&client->dev, "error disabling test mode\n"); + goto exit_dummy; + } + } + + if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0) dev_warn(&client->dev, "clock needs to be set\n"); device_set_wakeup_capable(&client->dev, 1); @@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client, err = PTR_ERR(s35390a->rtc); goto exit_dummy; } + + if (status1 & S35390A_FLAG_INT2) + rtc_update_irq(s35390a->rtc, 1, RTC_AF); + return 0; exit_dummy: diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index d01ad7e8078e..d44fb34df8fe 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) if (!is_power_of_2(freq)) return -EINVAL; + s3c_rtc_enable_clk(info); spin_lock_irq(&info->pie_lock); if (info->data->set_freq) info->data->set_freq(info, freq); spin_unlock_irq(&info->pie_lock); + s3c_rtc_disable_clk(info); return 0; } @@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) /* decode the alarm enable field */ if (alm_en & S3C2410_RTCALM_SECEN) alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); - else - alm_tm->tm_sec = -1; if (alm_en & S3C2410_RTCALM_MINEN) alm_tm->tm_min = bcd2bin(alm_tm->tm_min); - else - alm_tm->tm_min = -1; if (alm_en & S3C2410_RTCALM_HOUREN) alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); - else - alm_tm->tm_hour = -1; if (alm_en & S3C2410_RTCALM_DAYEN) alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); - else - alm_tm->tm_mday = -1; if (alm_en & S3C2410_RTCALM_MONEN) { alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); alm_tm->tm_mon -= 1; - } else { - alm_tm->tm_mon = -1; } if (alm_en & S3C2410_RTCALM_YEAREN) alm_tm->tm_year = bcd2bin(alm_tm->tm_year); - else - alm_tm->tm_year = -1; return 0; } @@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_setfreq(info, 1); - s3c_rtc_disable_clk(info); - return 0; err_nortc: diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 2b81dd4baf17..17b6235d67a5 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -30,7 +30,6 @@ #include <asm/rtc.h> #define DRV_NAME "sh-rtc" -#define DRV_VERSION "0.2.3" #define RTC_REG(r) ((r) * rtc_reg_size) @@ -482,7 +481,6 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR); if (tm->tm_mon > 0) tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ - tm->tm_year = 0xffff; wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0; @@ -501,52 +499,13 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, writeb(bin2bcd(value) | AR_ENB, rtc->regbase + reg_off); } -static int sh_rtc_check_alarm(struct rtc_time *tm) -{ - /* - * The original rtc says anything > 0xc0 is "don't care" or "match - * all" - most users use 0xff but rtc-dev uses -1 for the same thing. - * The original rtc doesn't support years - some things use -1 and - * some 0xffff. We use -1 to make out tests easier. - */ - if (tm->tm_year == 0xffff) - tm->tm_year = -1; - if (tm->tm_mon >= 0xff) - tm->tm_mon = -1; - if (tm->tm_mday >= 0xff) - tm->tm_mday = -1; - if (tm->tm_wday >= 0xff) - tm->tm_wday = -1; - if (tm->tm_hour >= 0xff) - tm->tm_hour = -1; - if (tm->tm_min >= 0xff) - tm->tm_min = -1; - if (tm->tm_sec >= 0xff) - tm->tm_sec = -1; - - if (tm->tm_year > 9999 || - tm->tm_mon >= 12 || - tm->tm_mday == 0 || tm->tm_mday >= 32 || - tm->tm_wday >= 7 || - tm->tm_hour >= 24 || - tm->tm_min >= 60 || - tm->tm_sec >= 60) - return -EINVAL; - - return 0; -} - static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { struct platform_device *pdev = to_platform_device(dev); struct sh_rtc *rtc = platform_get_drvdata(pdev); unsigned int rcr1; struct rtc_time *tm = &wkalrm->time; - int mon, err; - - err = sh_rtc_check_alarm(tm); - if (unlikely(err < 0)) - return err; + int mon; spin_lock_irq(&rtc->lock); @@ -790,7 +749,6 @@ static struct platform_driver sh_rtc_platform_driver = { module_platform_driver_probe(sh_rtc_platform_driver, sh_rtc_probe); MODULE_DESCRIPTION("SuperH on-chip RTC driver"); -MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, " "Jamie Lenehan <lenehan@twibble.org>, " "Angelo Castello <angelo.castello@st.com>"); diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 950c5d0b6dca..0f11c2a228e3 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -322,7 +322,7 @@ static int snvs_rtc_suspend(struct device *dev) struct snvs_rtc_data *data = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - enable_irq_wake(data->irq); + return enable_irq_wake(data->irq); return 0; } diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index ba6a83b5b5c9..a456cb6177ea 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -23,8 +23,6 @@ #include <linux/io.h> #include <linux/module.h> -#define DRV_VERSION "0.1" - #define RTC_REG_SIZE 0x20000 #define RTC_OFFSET 0x1fff0 @@ -366,4 +364,3 @@ module_platform_driver(stk17ta8_rtc_driver); MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index ca54d039da31..e6aaaa52e7fe 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -107,14 +107,19 @@ static struct stmp3xxx_wdt_pdata wdt_pdata = { static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) { + int rc = -1; struct platform_device *wdt_pdev = platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id); if (wdt_pdev) { wdt_pdev->dev.parent = &rtc_pdev->dev; wdt_pdev->dev.platform_data = &wdt_pdata; - platform_device_add(wdt_pdev); + rc = platform_device_add(wdt_pdev); } + + if (rc) + dev_err(&rtc_pdev->dev, + "failed to register stmp3xxx_rtc_wdt\n"); } #else static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 60232bd366ef..15ac597d54da 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) if (sec == 0) { /* alarm is disabled. */ alarm->enabled = 0; - alarm->time.tm_mon = -1; - alarm->time.tm_mday = -1; - alarm->time.tm_year = -1; - alarm->time.tm_hour = -1; - alarm->time.tm_min = -1; - alarm->time.tm_sec = -1; } else { /* alarm is enabled. */ alarm->enabled = 1; diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index e404faac6851..a3418a8a3796 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -344,7 +344,7 @@ static struct platform_driver tps6586x_rtc_driver = { }; module_platform_driver(tps6586x_rtc_driver); -MODULE_ALIAS("platform:rtc-tps6586x"); +MODULE_ALIAS("platform:tps6586x-rtc"); MODULE_DESCRIPTION("TI TPS6586x RTC driver"); MODULE_AUTHOR("Laxman dewangan <ldewangan@nvidia.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 7a0436329d6c..1f3117b5a83c 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c @@ -25,7 +25,7 @@ #include <linux/rtc.h> #include <linux/types.h> #include <linux/bcd.h> -#include <linux/rtc-v3020.h> +#include <linux/platform_data/rtc-v3020.h> #include <linux/delay.h> #include <linux/gpio.h> #include <linux/slab.h> diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 5638b7ba8b06..f08f18e4fcdf 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -24,8 +24,6 @@ #include <linux/module.h> #include <linux/bitops.h> -#define DRV_VERSION "1.0.8" - /* offsets into CCR area */ #define CCR_SEC 0 @@ -634,8 +632,6 @@ static int x1205_probe(struct i2c_client *client, if (x1205_validate_client(client) < 0) return -ENODEV; - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = devm_rtc_device_register(&client->dev, x1205_driver.driver.name, &x1205_rtc_ops, THIS_MODULE); @@ -693,4 +689,3 @@ MODULE_AUTHOR( "Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index 8b28762f06df..da18a8ae3c1d 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -45,6 +45,7 @@ #define RTC_INT_SEC BIT(0) #define RTC_INT_ALRM BIT(1) #define RTC_OSC_EN BIT(24) +#define RTC_BATT_EN BIT(31) #define RTC_CALIB_DEF 0x198233 #define RTC_CALIB_MASK 0x1FFFFF @@ -55,6 +56,7 @@ struct xlnx_rtc_dev { void __iomem *reg_base; int alarm_irq; int sec_irq; + int calibval; }; static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -62,21 +64,63 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); unsigned long new_time; - new_time = rtc_tm_to_time64(tm); + /* + * The value written will be updated after 1 sec into the + * seconds read register, so we need to program time +1 sec + * to get the correct time on read. + */ + new_time = rtc_tm_to_time64(tm) + 1; if (new_time > RTC_SEC_MAX_VAL) return -EINVAL; + /* + * Writing into calibration register will clear the Tick Counter and + * force the next second to be signaled exactly in 1 second period + */ + xrtcdev->calibval &= RTC_CALIB_MASK; + writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR)); + writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR); + /* + * Clear the rtc interrupt status register after setting the + * time. During a read_time function, the code should read the + * RTC_INT_STATUS register and if bit 0 is still 0, it means + * that one second has not elapsed yet since RTC was set and + * the current time should be read from SET_TIME_READ register; + * otherwise, CURRENT_TIME register is read to report the time + */ + writel(RTC_INT_SEC, xrtcdev->reg_base + RTC_INT_STS); + return 0; } static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm) { + u32 status; + unsigned long read_time; struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); - rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm); + status = readl(xrtcdev->reg_base + RTC_INT_STS); + + if (status & RTC_INT_SEC) { + /* + * RTC has updated the CURRENT_TIME with the time written into + * SET_TIME_WRITE register. + */ + rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm); + } else { + /* + * Time written in SET_TIME_WRITE has not yet updated into + * the seconds read register, so read the time from the + * SET_TIME_WRITE instead of CURRENT_TIME register. + * Since we add +1 sec while writing, we need to -1 sec while + * reading. + */ + read_time = readl(xrtcdev->reg_base + RTC_SET_TM_RD) - 1; + rtc_time64_to_tm(read_time, tm); + } return rtc_valid_tm(tm); } @@ -120,16 +164,23 @@ static int xlnx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) return 0; } -static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev, u32 calibval) +static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev) { + u32 rtc_ctrl; + + /* Enable RTC switch to battery when VCC_PSAUX is not available */ + rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL); + rtc_ctrl |= RTC_BATT_EN; + writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL); + /* * Based on crystal freq of 33.330 KHz * set the seconds counter and enable, set fractions counter * to default value suggested as per design spec * to correct RTC delay in frequency over period of time. */ - calibval &= RTC_CALIB_MASK; - writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR)); + xrtcdev->calibval &= RTC_CALIB_MASK; + writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR)); } static const struct rtc_class_ops xlnx_rtc_ops = { @@ -150,11 +201,9 @@ static irqreturn_t xlnx_rtc_interrupt(int irq, void *id) if (!(status & (RTC_INT_SEC | RTC_INT_ALRM))) return IRQ_NONE; - /* Clear interrupt */ - writel(status, xrtcdev->reg_base + RTC_INT_STS); + /* Clear RTC_INT_ALRM interrupt only */ + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); - if (status & RTC_INT_SEC) - rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_UF); if (status & RTC_INT_ALRM) rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF); @@ -166,7 +215,6 @@ static int xlnx_rtc_probe(struct platform_device *pdev) struct xlnx_rtc_dev *xrtcdev; struct resource *res; int ret; - unsigned int calibvalue; xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL); if (!xrtcdev) @@ -207,11 +255,11 @@ static int xlnx_rtc_probe(struct platform_device *pdev) } ret = of_property_read_u32(pdev->dev.of_node, "calibration", - &calibvalue); + &xrtcdev->calibval); if (ret) - calibvalue = RTC_CALIB_DEF; + xrtcdev->calibval = RTC_CALIB_DEF; - xlnx_init_rtc(xrtcdev, calibvalue); + xlnx_init_rtc(xrtcdev); device_init_wakeup(&pdev->dev, 1); |