aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-21 10:42:11 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-21 10:42:11 -0700
commit63d222b9d277c4d7bf08afd1631a7f8e327a825c (patch)
tree5a7167eebe02730c62b3137c9b9e89fa45329db7
parent10cd7158042bf9c949c19dbf0c7ee600d198ed39 (diff)
parentb9ba1eb0336877b9b83556fd30d2becda110fd8c (diff)
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 ...
-rw-r--r--Documentation/devicetree/bindings/rtc/maxim-ds1302.txt46
-rw-r--r--Documentation/devicetree/bindings/rtc/sa1100-rtc.txt2
-rw-r--r--drivers/rtc/Kconfig52
-rw-r--r--drivers/rtc/rtc-at91sam9.c2
-rw-r--r--drivers/rtc/rtc-cmos.c2
-rw-r--r--drivers/rtc/rtc-da9052.c13
-rw-r--r--drivers/rtc/rtc-ds1216.c3
-rw-r--r--drivers/rtc/rtc-ds1286.c3
-rw-r--r--drivers/rtc/rtc-ds1302.c348
-rw-r--r--drivers/rtc/rtc-ds1307.c23
-rw-r--r--drivers/rtc/rtc-ds1343.c2
-rw-r--r--drivers/rtc/rtc-ds1511.c3
-rw-r--r--drivers/rtc/rtc-ds1553.c3
-rw-r--r--drivers/rtc/rtc-ds1672.c5
-rw-r--r--drivers/rtc/rtc-ds1685.c4
-rw-r--r--drivers/rtc/rtc-ds1742.c3
-rw-r--r--drivers/rtc/rtc-ds3232.c9
-rw-r--r--drivers/rtc/rtc-ep93xx.c3
-rw-r--r--drivers/rtc/rtc-gemini.c1
-rw-r--r--drivers/rtc/rtc-hym8563.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c5
-rw-r--r--drivers/rtc/rtc-isl1208.c6
-rw-r--r--drivers/rtc/rtc-m41t80.c447
-rw-r--r--drivers/rtc/rtc-m48t35.c3
-rw-r--r--drivers/rtc/rtc-m48t86.c4
-rw-r--r--drivers/rtc/rtc-max6900.c5
-rw-r--r--drivers/rtc/rtc-mc13xxx.c19
-rw-r--r--drivers/rtc/rtc-mrst.c2
-rw-r--r--drivers/rtc/rtc-mxc.c3
-rw-r--r--drivers/rtc/rtc-pcf2123.c4
-rw-r--r--drivers/rtc/rtc-pcf8563.c7
-rw-r--r--drivers/rtc/rtc-rs5c313.c2
-rw-r--r--drivers/rtc/rtc-rs5c348.c4
-rw-r--r--drivers/rtc/rtc-rs5c372.c18
-rw-r--r--drivers/rtc/rtc-rv3029c2.c596
-rw-r--r--drivers/rtc/rtc-rx8581.c5
-rw-r--r--drivers/rtc/rtc-sh.c2
-rw-r--r--drivers/rtc/rtc-snvs.c2
-rw-r--r--drivers/rtc/rtc-stk17ta8.c3
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c7
-rw-r--r--drivers/rtc/rtc-tps6586x.c2
-rw-r--r--drivers/rtc/rtc-x1205.c5
-rw-r--r--drivers/rtc/rtc-zynqmp.c74
43 files changed, 1019 insertions, 735 deletions
diff --git a/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt b/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt
new file mode 100644
index 000000000000..ba470c56cdec
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt
@@ -0,0 +1,46 @@
+* Maxim/Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+The device uses the standard MicroWire half-duplex transfer timing.
+Master output is set on low clock and sensed by the RTC on the rising
+edge. Master input is set by the RTC on the trailing edge and is sensed
+by the master on low clock.
+
+Required properties:
+
+- compatible : Should be "maxim,ds1302"
+
+Required SPI properties:
+
+- reg : Should be address of the device chip select within
+ the controller.
+
+- spi-max-frequency : DS-1302 has 500 kHz if powered at 2.2V,
+ and 2MHz if powered at 5V.
+
+- spi-3wire : The device has a shared signal IN/OUT line.
+
+- spi-lsb-first : DS-1302 requires least significant bit first
+ transfers.
+
+- spi-cs-high: DS-1302 has active high chip select line. This is
+ required unless inverted in hardware.
+
+Example:
+
+spi@901c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "icpdas,lp8841-spi-rtc";
+ reg = <0x901c 0x1>;
+
+ rtc@0 {
+ compatible = "maxim,ds1302";
+ reg = <0>;
+ spi-max-frequency = <500000>;
+ spi-3wire;
+ spi-lsb-first;
+ spi-cs-high;
+ };
+};
diff --git a/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt b/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt
index 0cda19ad4859..968ac820254b 100644
--- a/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt
@@ -13,5 +13,5 @@ Example:
compatible = "mrvl,mmp-rtc";
reg = <0xd4010000 0x1000>;
interrupts = <5>, <6>;
- interrupt-name = "rtc 1Hz", "rtc alarm";
+ interrupt-names = "rtc 1Hz", "rtc alarm";
};
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);