diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 20:42:11 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 20:42:11 +0300 |
commit | 63d222b9d277c4d7bf08afd1631a7f8e327a825c (patch) | |
tree | 5a7167eebe02730c62b3137c9b9e89fa45329db7 /drivers | |
parent | 10cd7158042bf9c949c19dbf0c7ee600d198ed39 (diff) | |
parent | b9ba1eb0336877b9b83556fd30d2becda110fd8c (diff) | |
download | linux-63d222b9d277c4d7bf08afd1631a7f8e327a825c.tar.xz |
Merge tag 'rtc-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"Subsystem wide cleanups:
- Use IS_ENABLED() instead of checking for built-in or module
- remove useless DRV_VERSION
- remove CLK_IS_ROOT
- remove UIE signaling
Drivers:
- ds1302: rewritten to be a proper SPI device driver
- m41t80: huge cleanup, alarm, wakelarm ans oscialltor failure
detection support
- rv3029: switch to regmap to handle rv3049, alarm support, fixes
- zynqmp: enable switching to battery power, fixes
- small fixes for at91sam9, da9053, ds1307, ds1685, ds3232, r2025,
sa1100, snvs, stmp3xxx, tps6586x"
* tag 'rtc-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (40 commits)
rtc: tps6586x: rename so module can be autoloaded
rtc: rv3029: hide unused i2c device table
rtc: rs5c372: r2025: fix check for 'oscillator halted' condition
rtc: rv3029: add alarm IRQ
rtc: rv3029: fix set_time function
rtc: rv3029: fix alarm support
rtc: rv3029: Remove some checks and warnings
rtc: rv3029: Add support of RV3049
rtc: rv3029: convert to use regmap
rtc: rv3029: remove 'i2c' in functions names
rtc: stmp3xxx: print message on error
rtc: Use IS_ENABLED() instead of checking for built-in or module
rtc: ds3232: fix call trace when rtc->ops_lock is used as NULL
rtc: snvs: return error in case enable_irq_wake fails
rtc: zynqmp: Update seconds time programming logic
rtc: sa1100: DT spelling s/interrupt-name/interrupt-names/
rtc: mc13xxx: remove UIE signaling
rtc: mxc: remove UIE signaling
rtc: ds1307: Remove CLK_IS_ROOT
rtc: hym8563: Remove CLK_IS_ROOT
...
Diffstat (limited to 'drivers')
41 files changed, 972 insertions, 734 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3e84315c6f12..18639e0cb6e2 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -573,24 +573,6 @@ 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" help @@ -634,6 +616,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 @@ -777,6 +768,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> @@ -834,12 +844,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/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 7206e2fa4383..99732e6f8c3b 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"); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 84fb541038be..fbe9c72438e1 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -401,7 +401,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) { diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 1ba4371cbc2d..a20bcf0e33cd 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -302,6 +302,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 +316,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-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..756e509f6ed2 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -20,8 +20,6 @@ #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-ds1307.c b/drivers/rtc/rtc-ds1307.c index ecb7dbae9be9..821d9c089cdb 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, @@ -538,12 +542,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 +553,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; } @@ -1144,12 +1151,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, }, }; diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 3d389bd8a289..23fa9f0cb5e3 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 @@ -747,4 +746,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..b3ce3c652fcd 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 */ @@ -2213,6 +2211,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 +2223,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-ds3232.c b/drivers/rtc/rtc-ds3232.c index 7edc889729c5..04fbd7fffd0d 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -369,6 +369,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 +385,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-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-hym8563.c b/drivers/rtc/rtc-hym8563.c index b1b4746a0eab..207270376b55 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -413,7 +413,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-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..d1bf93a87200 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 (i2c_transfer(client->adapter, msgs, 2) < 0) { - dev_err(&client->dev, "read error\n"); + if (flags & M41T80_FLAGS_OF) { + dev_err(&client->dev, "Oscillator failure, data is invalid.\n"); + return -EINVAL; + } + + 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,117 @@ 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_info(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_wday = -1; + alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f); + alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f); + alrm->time.tm_year = -1; + + 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) +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 +348,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 +378,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 +419,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 +429,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 +494,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 +736,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 +818,30 @@ 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(&client->dev, m41t80_remove_sysfs_group, + &client->dev); + if (rc) { + m41t80_remove_sysfs_group(&client->dev); + 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) 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..f72b91f2501f 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -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-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-mrst.c b/drivers/rtc/rtc-mrst.c index 548ea6f6f384..0094d9bdd1e6 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -266,7 +266,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-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index da27738b1242..f22e060709e5 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 */ @@ -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-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index c8f95b8e463a..b9ddbb001283 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) @@ -535,7 +533,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 +578,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 +658,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-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..ef86229428fc 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 @@ -412,7 +409,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 +438,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 +506,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 +637,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 +693,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-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-sh.c b/drivers/rtc/rtc-sh.c index 2b81dd4baf17..a45845a571e5 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) @@ -790,7 +789,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-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-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); |