summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/rtc/dallas,ds1390.txt18
-rw-r--r--Documentation/devicetree/bindings/rtc/pcf8563.txt25
-rw-r--r--drivers/rtc/Kconfig13
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-ab8500.c6
-rw-r--r--drivers/rtc/rtc-at91rm9200.c2
-rw-r--r--drivers/rtc/rtc-da9063.c18
-rw-r--r--drivers/rtc/rtc-davinci.c1
-rw-r--r--drivers/rtc/rtc-ds1307.c4
-rw-r--r--drivers/rtc/rtc-ds1343.c9
-rw-r--r--drivers/rtc/rtc-ds1390.c65
-rw-r--r--drivers/rtc/rtc-isl12057.c10
-rw-r--r--drivers/rtc/rtc-isl1208.c2
-rw-r--r--drivers/rtc/rtc-opal.c9
-rw-r--r--drivers/rtc/rtc-pcf2127.c47
-rw-r--r--drivers/rtc/rtc-pcf85063.c8
-rw-r--r--drivers/rtc/rtc-pcf8563.c170
-rw-r--r--drivers/rtc/rtc-pl031.c13
-rw-r--r--drivers/rtc/rtc-rv8803.c521
-rw-r--r--drivers/rtc/rtc-rx8025.c4
-rw-r--r--drivers/rtc/rtc-s3c.c16
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c27
-rw-r--r--tools/testing/selftests/timers/rtctest.c2
23 files changed, 908 insertions, 83 deletions
diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1390.txt b/Documentation/devicetree/bindings/rtc/dallas,ds1390.txt
new file mode 100644
index 000000000000..8e76f2648796
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/dallas,ds1390.txt
@@ -0,0 +1,18 @@
+* Dallas DS1390		SPI Serial Real-Time Clock
+
+Required properties:
+- compatible: Should contain "dallas,ds1390".
+- reg: SPI address for chip
+
+Optional properties:
+- trickle-resistor-ohms : Selected resistor for trickle charger
+	Values usable for ds1390 are 250, 2000, 4000
+	Should be given if trickle charger should be enabled
+- trickle-diode-disable : Do not use internal trickle charger diode
+	Should be given if internal trickle charger diode should be disabled
+Example:
+	ds1390: rtc@68 {
+		compatible = "dallas,ds1390";
+		trickle-resistor-ohms = <250>;
+		reg = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt
new file mode 100644
index 000000000000..72f6d2c9665e
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/pcf8563.txt
@@ -0,0 +1,25 @@
+* Philips PCF8563/Epson RTC8564 Real Time Clock
+
+Philips PCF8563/Epson RTC8564 Real Time Clock
+
+Required properties:
+see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+
+Optional property:
+- #clock-cells: Should be 0.
+- clock-output-names:
+  overwrite the default clock name "pcf8563-clkout"
+
+Example:
+
+pcf8563: pcf8563@51 {
+	compatible = "nxp,pcf8563";
+	reg = <0x51>;
+	#clock-cells = <0>;
+};
+
+device {
+...
+	clocks = <&pcf8563>;
+...
+};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9d4290617cee..2a524244afec 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -593,6 +593,15 @@ config RTC_DRV_RV3029C2
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rv3029c2.
 
+config RTC_DRV_RV8803
+	tristate "Micro Crystal RV8803"
+	help
+	  If you say yes here you get support for the Micro Crystal
+	  RV8803 RTC chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-rv8803.
+
 config RTC_DRV_S5M
 	tristate "Samsung S2M/S5M series"
 	depends on MFD_SEC_CORE
@@ -666,8 +675,8 @@ config RTC_DRV_DS1390
 	  If you say yes here you get support for the
 	  Dallas/Maxim DS1390/93/94 chips.
 
-	  This driver only supports the RTC feature, and not other chip
-	  features such as alarms and trickle charging.
+	  This driver supports the RTC feature and trickle charging but not
+	  other chip features such as alarms.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1390.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index e491eb524434..231f76451615 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o
 obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
 obj-$(CONFIG_RTC_DRV_RV3029C2)	+= rtc-rv3029c2.o
+obj-$(CONFIG_RTC_DRV_RV8803)	+= rtc-rv8803.o
 obj-$(CONFIG_RTC_DRV_RX4581)	+= rtc-rx4581.o
 obj-$(CONFIG_RTC_DRV_RX8025)	+= rtc-rx8025.o
 obj-$(CONFIG_RTC_DRV_RX8581)	+= rtc-rx8581.o
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 51407c4c7bd2..24a0af650a1b 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -18,6 +18,7 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/pm_wakeirq.h>
 
 #define AB8500_RTC_SOFF_STAT_REG	0x00
 #define AB8500_RTC_CC_CONF_REG		0x01
@@ -493,11 +494,12 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
 	}
 
 	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-			rtc_alarm_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+			rtc_alarm_handler, IRQF_ONESHOT,
 			"ab8500-rtc", rtc);
 	if (err < 0)
 		return err;
 
+	dev_pm_set_wake_irq(&pdev->dev, irq);
 	platform_set_drvdata(pdev, rtc);
 
 	err = ab8500_sysfs_rtc_register(&pdev->dev);
@@ -513,6 +515,8 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
 
 static int ab8500_rtc_remove(struct platform_device *pdev)
 {
+	dev_pm_clear_wake_irq(&pdev->dev);
+	device_init_wakeup(&pdev->dev, false);
 	ab8500_sysfs_rtc_unregister(&pdev->dev);
 
 	return 0;
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index cb62e214b52a..b60fd477778f 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -495,6 +495,8 @@ static int at91_rtc_suspend(struct device *dev)
 	/* this IRQ is shared with DBGU and other hardware which isn't
 	 * necessarily doing PM like we are...
 	 */
+	at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
+
 	at91_rtc_imr = at91_rtc_read_imr()
 			& (AT91_RTC_ALARM|AT91_RTC_SECEV);
 	if (at91_rtc_imr) {
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index 00a8f7f4f87c..284b587da65c 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -1,15 +1,15 @@
 /* rtc-da9063.c - Real time clock device driver for DA9063
- * Copyright (C) 2013-14  Dialog Semiconductor Ltd.
+ * Copyright (C) 2013-2015  Dialog Semiconductor Ltd.
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/delay.h>
@@ -516,5 +516,5 @@ module_platform_driver(da9063_rtc_driver);
 
 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
 MODULE_DESCRIPTION("Real time clock device driver for Dialog DA9063");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DA9063_DRVNAME_RTC);
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index c84f46168a52..c5432bf64e1c 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -546,7 +546,6 @@ static int __exit davinci_rtc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver davinci_rtc_driver = {
-	.probe		= davinci_rtc_probe,
 	.remove		= __exit_p(davinci_rtc_remove),
 	.driver		= {
 		.name = "rtc_davinci",
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index a705e6490808..188006c55ce0 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -718,9 +718,9 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 	regs[3] = bin2bcd(t->time.tm_sec);
 	regs[4] = bin2bcd(t->time.tm_min);
 	regs[5] = bin2bcd(t->time.tm_hour);
-	regs[6] = bin2bcd(t->time.tm_wday) + 1;
+	regs[6] = bin2bcd(t->time.tm_wday + 1);
 	regs[7] = bin2bcd(t->time.tm_mday);
-	regs[8] = bin2bcd(t->time.tm_mon) + 1;
+	regs[8] = bin2bcd(t->time.tm_mon + 1);
 
 	/* Clear the alarm 0 interrupt flag. */
 	regs[6] &= ~MCP794XX_BIT_ALMX_IF;
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index 07371a9e3793..3d389bd8a289 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -21,6 +21,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/pm.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 
 #define DS1343_DRV_VERSION	"01.00"
@@ -663,15 +664,15 @@ static int ds1343_probe(struct spi_device *spi)
 
 	if (priv->irq >= 0) {
 		res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
-						ds1343_thread,
-						IRQF_NO_SUSPEND | IRQF_ONESHOT,
+						ds1343_thread, IRQF_ONESHOT,
 						"ds1343", priv);
 		if (res) {
 			priv->irq = -1;
 			dev_err(&spi->dev,
 				"unable to request irq for rtc ds1343\n");
 		} else {
-			device_set_wakeup_capable(&spi->dev, 1);
+			device_init_wakeup(&spi->dev, true);
+			dev_pm_set_wake_irq(&spi->dev, spi->irq);
 		}
 	}
 
@@ -692,6 +693,8 @@ static int ds1343_remove(struct spi_device *spi)
 		priv->irqen &= ~RTC_AF;
 		mutex_unlock(&priv->mutex);
 
+		dev_pm_clear_wake_irq(&spi->dev);
+		device_init_wakeup(&spi->dev, false);
 		devm_free_irq(&spi->dev, spi->irq, priv);
 	}
 
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index 4c229c97ef97..aa0d2c6f1edc 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -20,6 +20,7 @@
 #include <linux/spi/spi.h>
 #include <linux/bcd.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #define DS1390_REG_100THS		0x00
 #define DS1390_REG_SECONDS		0x01
@@ -40,11 +41,31 @@
 #define DS1390_REG_STATUS		0x0E
 #define DS1390_REG_TRICKLE		0x0F
 
+#define DS1390_TRICKLE_CHARGER_ENABLE	0xA0
+#define DS1390_TRICKLE_CHARGER_250_OHM	0x01
+#define DS1390_TRICKLE_CHARGER_2K_OHM	0x02
+#define DS1390_TRICKLE_CHARGER_4K_OHM	0x03
+#define DS1390_TRICKLE_CHARGER_NO_DIODE	0x04
+#define DS1390_TRICKLE_CHARGER_DIODE	0x08
+
 struct ds1390 {
 	struct rtc_device *rtc;
 	u8 txrx_buf[9];	/* cmd + 8 registers */
 };
 
+static void ds1390_set_reg(struct device *dev, unsigned char address,
+			   unsigned char data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	unsigned char buf[2];
+
+	/* MSB must be '1' to write */
+	buf[0] = address | 0x80;
+	buf[1] = data;
+
+	spi_write(spi, buf, 2);
+}
+
 static int ds1390_get_reg(struct device *dev, unsigned char address,
 				unsigned char *data)
 {
@@ -62,11 +83,50 @@ static int ds1390_get_reg(struct device *dev, unsigned char address,
 	if (status != 0)
 		return status;
 
-	*data = chip->txrx_buf[1];
+	*data = chip->txrx_buf[0];
 
 	return 0;
 }
 
+static void ds1390_trickle_of_init(struct spi_device *spi)
+{
+	u32 ohms = 0;
+	u8 value;
+
+	if (of_property_read_u32(spi->dev.of_node, "trickle-resistor-ohms",
+				 &ohms))
+		goto out;
+
+	/* Enable charger */
+	value = DS1390_TRICKLE_CHARGER_ENABLE;
+	if (of_property_read_bool(spi->dev.of_node, "trickle-diode-disable"))
+		value |= DS1390_TRICKLE_CHARGER_NO_DIODE;
+	else
+		value |= DS1390_TRICKLE_CHARGER_DIODE;
+
+	/* Resistor select */
+	switch (ohms) {
+	case 250:
+		value |= DS1390_TRICKLE_CHARGER_250_OHM;
+		break;
+	case 2000:
+		value |= DS1390_TRICKLE_CHARGER_2K_OHM;
+		break;
+	case 4000:
+		value |= DS1390_TRICKLE_CHARGER_4K_OHM;
+		break;
+	default:
+		dev_warn(&spi->dev,
+			 "Unsupported ohm value %02ux in dt\n", ohms);
+		return;
+	}
+
+	ds1390_set_reg(&spi->dev, DS1390_REG_TRICKLE, value);
+
+out:
+	return;
+}
+
 static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
 {
 	struct spi_device *spi = to_spi_device(dev);
@@ -143,6 +203,9 @@ static int ds1390_probe(struct spi_device *spi)
 		return res;
 	}
 
+	if (spi->dev.of_node)
+		ds1390_trickle_of_init(spi);
+
 	chip->rtc = devm_rtc_device_register(&spi->dev, "ds1390",
 					&ds1390_rtc_ops, THIS_MODULE);
 	if (IS_ERR(chip->rtc)) {
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c
index a0462e5430c7..54328d4ac0d3 100644
--- a/drivers/rtc/rtc-isl12057.c
+++ b/drivers/rtc/rtc-isl12057.c
@@ -466,9 +466,8 @@ static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap)
  * is for instance the case on ReadyNAS 102, 104 and 2120. On those
  * devices with no IRQ driectly connected to the SoC, the RTC chip
  * can be forced as a wakeup source by stating that explicitly in
- * the device's .dts file using the "isil,irq2-can-wakeup-machine"
- * boolean property. This will guarantee 'wakealarm' sysfs entry is
- * available on the device.
+ * the device's .dts file using the "wakeup-source" boolean property.
+ * This will guarantee 'wakealarm' sysfs entry is available on the device.
  *
  * The function below returns 1, i.e. the capability of the chip to
  * wakeup the device, based on IRQ availability or if the boolean
@@ -479,8 +478,9 @@ static bool isl12057_can_wakeup_machine(struct device *dev)
 {
 	struct isl12057_rtc_data *data = dev_get_drvdata(dev);
 
-	return (data->irq || of_property_read_bool(dev->of_node,
-					      "isil,irq2-can-wakeup-machine"));
+	return data->irq || of_property_read_bool(dev->of_node, "wakeup-source")
+		|| of_property_read_bool(dev->of_node, /* legacy */
+					 "isil,irq2-can-wakeup-machine");
 }
 #else
 static bool isl12057_can_wakeup_machine(struct device *dev)
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index aa3b8f1b34d9..b57a304ff62c 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -638,7 +638,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (client->irq > 0) {
 		rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
 					       isl1208_rtc_interrupt,
-					       IRQF_SHARED,
+					       IRQF_SHARED | IRQF_ONESHOT,
 					       isl1208_driver.driver.name,
 					       client);
 		if (!rc) {
diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c
index 6fbf9e617151..df39ce02a99d 100644
--- a/drivers/rtc/rtc-opal.c
+++ b/drivers/rtc/rtc-opal.c
@@ -152,10 +152,10 @@ exit:
 /* Set Timed Power-On */
 static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	u64 h_m_s_ms = 0, token;
+	u64 h_m_s_ms = 0;
 	struct opal_msg msg;
 	u32 y_m_d = 0;
-	int rc;
+	int token, rc;
 
 	tm_to_opal(&alarm->time, &y_m_d, &h_m_s_ms);
 
@@ -199,8 +199,9 @@ static int opal_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo",
-						 NULL)) {
+	if (pdev->dev.of_node &&
+	    (of_property_read_bool(pdev->dev.of_node, "wakeup-source") ||
+	     of_property_read_bool(pdev->dev.of_node, "has-tpo")/* legacy */)) {
 		device_set_wakeup_capable(&pdev->dev, true);
 		opal_rtc_ops.read_alarm	= opal_get_tpo_time;
 		opal_rtc_ops.set_alarm = opal_set_tpo_time;
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 4b11d31f7174..629bfdf8c745 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -20,11 +20,12 @@
 #include <linux/module.h>
 #include <linux/of.h>
 
-#define DRV_VERSION "0.0.1"
-
 #define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
 #define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */
+
 #define PCF2127_REG_CTRL3       (0x02)  /* Control Register 3 */
+#define PCF2127_REG_CTRL3_BLF		BIT(2)
+
 #define PCF2127_REG_SC          (0x03)  /* datetime */
 #define PCF2127_REG_MN          (0x04)
 #define PCF2127_REG_HR          (0x05)
@@ -39,8 +40,6 @@ static struct i2c_driver pcf2127_driver;
 
 struct pcf2127 {
 	struct rtc_device *rtc;
-	int voltage_low; /* indicates if a low_voltage was detected */
-	int oscillator_failed; /* OSF was detected and date is unreliable */
 };
 
 /*
@@ -49,7 +48,6 @@ struct pcf2127 {
  */
 static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-	struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
 	unsigned char buf[10] = { PCF2127_REG_CTRL1 };
 
 	/* read registers */
@@ -59,18 +57,15 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 		return -EIO;
 	}
 
-	if (buf[PCF2127_REG_CTRL3] & 0x04) {
-		pcf2127->voltage_low = 1;
+	if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
 		dev_info(&client->dev,
 			"low voltage detected, check/replace RTC battery.\n");
-	}
 
 	if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
 		/*
 		 * no need clear the flag here,
 		 * it will be cleared once the new date is saved
 		 */
-		pcf2127->oscillator_failed = 1;
 		dev_warn(&client->dev,
 			 "oscillator stop detected, date/time is not reliable\n");
 		return -EINVAL;
@@ -107,7 +102,6 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 
 static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-	struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
 	unsigned char buf[8];
 	int i = 0, err;
 
@@ -141,9 +135,6 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 		return -EIO;
 	}
 
-	/* clear OSF flag in client data */
-	pcf2127->oscillator_failed = 0;
-
 	return 0;
 }
 
@@ -151,17 +142,28 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int pcf2127_rtc_ioctl(struct device *dev,
 				unsigned int cmd, unsigned long arg)
 {
-	struct pcf2127 *pcf2127 = i2c_get_clientdata(to_i2c_client(dev));
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char buf = PCF2127_REG_CTRL3;
+	int touser;
+	int ret;
 
 	switch (cmd) {
 	case RTC_VL_READ:
-		if (pcf2127->voltage_low)
-			dev_info(dev, "low voltage detected, check/replace battery\n");
-		if (pcf2127->oscillator_failed)
-			dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
+		ret = i2c_master_send(client, &buf, 1);
+		if (!ret)
+			ret = -EIO;
+		if (ret < 0)
+			return ret;
+
+		ret = i2c_master_recv(client, &buf, 1);
+		if (!ret)
+			ret = -EIO;
+		if (ret < 0)
+			return ret;
 
-		if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
-					sizeof(int)))
+		touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;
+
+		if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
 			return -EFAULT;
 		return 0;
 	default:
@@ -203,8 +205,6 @@ static int pcf2127_probe(struct i2c_client *client,
 	if (!pcf2127)
 		return -ENOMEM;
 
-	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
-
 	i2c_set_clientdata(client, pcf2127);
 
 	pcf2127->rtc = devm_rtc_device_register(&client->dev,
@@ -241,5 +241,4 @@ module_i2c_driver(pcf2127_driver);
 
 MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
 MODULE_DESCRIPTION("NXP PCF2127 RTC driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index b6d73dd881f2..63334cbeca41 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -80,13 +80,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 	pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
 		(tm->tm_year >= 100) : (tm->tm_year < 100);
 
-	/* the clock can give out invalid datetime, but we cannot return
-	 * -EINVAL otherwise hwclock will refuse to set the time on bootup.
-	 */
-	if (rtc_valid_tm(tm) < 0)
-		dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
-	return 0;
+	return rtc_valid_tm(tm);
 }
 
 static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index e569243db57e..c8f95b8e463a 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -14,6 +14,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/clk-provider.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
@@ -40,7 +41,14 @@
 
 #define PCF8563_REG_AMN		0x09 /* alarm */
 
-#define PCF8563_REG_CLKO	0x0D /* clock out */
+#define PCF8563_REG_CLKO		0x0D /* clock out */
+#define PCF8563_REG_CLKO_FE		0x80 /* clock out enabled */
+#define PCF8563_REG_CLKO_F_MASK		0x03 /* frequenc mask */
+#define PCF8563_REG_CLKO_F_32768HZ	0x00
+#define PCF8563_REG_CLKO_F_1024HZ	0x01
+#define PCF8563_REG_CLKO_F_32HZ		0x02
+#define PCF8563_REG_CLKO_F_1HZ		0x03
+
 #define PCF8563_REG_TMRC	0x0E /* timer control */
 #define PCF8563_TMRC_ENABLE	BIT(7)
 #define PCF8563_TMRC_4096	0
@@ -76,6 +84,9 @@ struct pcf8563 {
 	int voltage_low; /* incicates if a low_voltage was detected */
 
 	struct i2c_client *client;
+#ifdef CONFIG_COMMON_CLK
+	struct clk_hw		clkout_hw;
+#endif
 };
 
 static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
@@ -390,6 +401,158 @@ static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
 	return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
 }
 
+#ifdef CONFIG_COMMON_CLK
+/*
+ * Handling of the clkout
+ */
+
+#define clkout_hw_to_pcf8563(_hw) container_of(_hw, struct pcf8563, clkout_hw)
+
+static int clkout_rates[] = {
+	32768,
+	1024,
+	32,
+	1,
+};
+
+static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+	struct i2c_client *client = pcf8563->client;
+	unsigned char buf;
+	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+	if (ret < 0)
+		return 0;
+
+	buf &= PCF8563_REG_CLKO_F_MASK;
+	return clkout_rates[ret];
+}
+
+static long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *prate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+		if (clkout_rates[i] <= rate)
+			return clkout_rates[i];
+
+	return 0;
+}
+
+static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+	struct i2c_client *client = pcf8563->client;
+	unsigned char buf;
+	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+	int i;
+
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+		if (clkout_rates[i] == rate) {
+			buf &= ~PCF8563_REG_CLKO_F_MASK;
+			buf |= i;
+			ret = pcf8563_write_block_data(client,
+						       PCF8563_REG_CLKO, 1,
+						       &buf);
+			return ret;
+		}
+
+	return -EINVAL;
+}
+
+static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
+{
+	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+	struct i2c_client *client = pcf8563->client;
+	unsigned char buf;
+	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+	if (ret < 0)
+		return ret;
+
+	if (enable)
+		buf |= PCF8563_REG_CLKO_FE;
+	else
+		buf &= ~PCF8563_REG_CLKO_FE;
+
+	ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+	return ret;
+}
+
+static int pcf8563_clkout_prepare(struct clk_hw *hw)
+{
+	return pcf8563_clkout_control(hw, 1);
+}
+
+static void pcf8563_clkout_unprepare(struct clk_hw *hw)
+{
+	pcf8563_clkout_control(hw, 0);
+}
+
+static int pcf8563_clkout_is_prepared(struct clk_hw *hw)
+{
+	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+	struct i2c_client *client = pcf8563->client;
+	unsigned char buf;
+	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+	if (ret < 0)
+		return ret;
+
+	return !!(buf & PCF8563_REG_CLKO_FE);
+}
+
+static const struct clk_ops pcf8563_clkout_ops = {
+	.prepare = pcf8563_clkout_prepare,
+	.unprepare = pcf8563_clkout_unprepare,
+	.is_prepared = pcf8563_clkout_is_prepared,
+	.recalc_rate = pcf8563_clkout_recalc_rate,
+	.round_rate = pcf8563_clkout_round_rate,
+	.set_rate = pcf8563_clkout_set_rate,
+};
+
+static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
+{
+	struct i2c_client *client = pcf8563->client;
+	struct device_node *node = client->dev.of_node;
+	struct clk *clk;
+	struct clk_init_data init;
+	int ret;
+	unsigned char buf;
+
+	/* disable the clkout output */
+	buf = 0;
+	ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	init.name = "pcf8563-clkout";
+	init.ops = &pcf8563_clkout_ops;
+	init.flags = CLK_IS_ROOT;
+	init.parent_names = NULL;
+	init.num_parents = 0;
+	pcf8563->clkout_hw.init = &init;
+
+	/* optional override of the clockname */
+	of_property_read_string(node, "clock-output-names", &init.name);
+
+	/* register the clock */
+	clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+	return clk;
+}
+#endif
+
 static const struct rtc_class_ops pcf8563_rtc_ops = {
 	.ioctl		= pcf8563_rtc_ioctl,
 	.read_time	= pcf8563_rtc_read_time,
@@ -459,6 +622,11 @@ static int pcf8563_probe(struct i2c_client *client,
 
 	}
 
+#ifdef CONFIG_COMMON_CLK
+	/* register clk in common clk framework */
+	pcf8563_clkout_register_clk(pcf8563);
+#endif
+
 	/* the pcf8563 alarm only supports a minute accuracy */
 	pcf8563->rtc->uie_unsupported = 1;
 
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 41dcb7ddb906..e1687e19c59f 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/bcd.h>
 #include <linux/delay.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 
 /*
@@ -305,6 +306,8 @@ static int pl031_remove(struct amba_device *adev)
 {
 	struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
 
+	dev_pm_clear_wake_irq(&adev->dev);
+	device_init_wakeup(&adev->dev, false);
 	free_irq(adev->irq[0], ldata);
 	rtc_device_unregister(ldata->rtc);
 	iounmap(ldata->base);
@@ -370,7 +373,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
 		}
 	}
 
-	device_init_wakeup(&adev->dev, 1);
+	device_init_wakeup(&adev->dev, true);
 	ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
 					THIS_MODULE);
 	if (IS_ERR(ldata->rtc)) {
@@ -383,7 +386,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
 		ret = -EIO;
 		goto out_no_irq;
 	}
-
+	dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
 	return 0;
 
 out_no_irq:
@@ -408,7 +411,6 @@ static struct pl031_vendor_data arm_pl031 = {
 		.set_alarm = pl031_set_alarm,
 		.alarm_irq_enable = pl031_alarm_irq_enable,
 	},
-	.irqflags = IRQF_NO_SUSPEND,
 };
 
 /* The First ST derivative */
@@ -422,7 +424,6 @@ static struct pl031_vendor_data stv1_pl031 = {
 	},
 	.clockwatch = true,
 	.st_weekday = true,
-	.irqflags = IRQF_NO_SUSPEND,
 };
 
 /* And the second ST derivative */
@@ -439,8 +440,10 @@ static struct pl031_vendor_data stv2_pl031 = {
 	/*
 	 * This variant shares the IRQ with another block and must not
 	 * suspend that IRQ line.
+	 * TODO check if it shares with IRQF_NO_SUSPEND user, else we can
+	 * remove IRQF_COND_SUSPEND
 	 */
-	.irqflags = IRQF_SHARED | IRQF_NO_SUSPEND,
+	.irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
 };
 
 static struct amba_id pl031_ids[] = {
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
new file mode 100644
index 000000000000..e7329e21bfe3
--- /dev/null
+++ b/drivers/rtc/rtc-rv8803.c
@@ -0,0 +1,521 @@
+/*
+ * RTC driver for the Micro Crystal RV8803
+ *
+ * Copyright (C) 2015 Micro Crystal SA
+ *
+ * Alexandre Belloni <alexandre.belloni@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bcd.h>
+#include <linux/bitops.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+#define RV8803_SEC			0x00
+#define RV8803_MIN			0x01
+#define RV8803_HOUR			0x02
+#define RV8803_WEEK			0x03
+#define RV8803_DAY			0x04
+#define RV8803_MONTH			0x05
+#define RV8803_YEAR			0x06
+#define RV8803_RAM			0x07
+#define RV8803_ALARM_MIN		0x08
+#define RV8803_ALARM_HOUR		0x09
+#define RV8803_ALARM_WEEK_OR_DAY	0x0A
+#define RV8803_EXT			0x0D
+#define RV8803_FLAG			0x0E
+#define RV8803_CTRL			0x0F
+
+#define RV8803_EXT_WADA			BIT(6)
+
+#define RV8803_FLAG_V1F			BIT(0)
+#define RV8803_FLAG_V2F			BIT(1)
+#define RV8803_FLAG_AF			BIT(3)
+#define RV8803_FLAG_TF			BIT(4)
+#define RV8803_FLAG_UF			BIT(5)
+
+#define RV8803_CTRL_RESET		BIT(0)
+
+#define RV8803_CTRL_EIE			BIT(2)
+#define RV8803_CTRL_AIE			BIT(3)
+#define RV8803_CTRL_TIE			BIT(4)
+#define RV8803_CTRL_UIE			BIT(5)
+
+struct rv8803_data {
+	struct i2c_client *client;
+	struct rtc_device *rtc;
+	spinlock_t flags_lock;
+	u8 ctrl;
+};
+
+static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
+{
+	struct i2c_client *client = dev_id;
+	struct rv8803_data *rv8803 = i2c_get_clientdata(client);
+	unsigned long events = 0;
+	u8 flags;
+
+	spin_lock(&rv8803->flags_lock);
+
+	flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+	if (flags <= 0) {
+		spin_unlock(&rv8803->flags_lock);
+		return IRQ_NONE;
+	}
+
+	if (flags & RV8803_FLAG_V1F)
+		dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
+
+	if (flags & RV8803_FLAG_V2F)
+		dev_warn(&client->dev, "Voltage low, data loss detected.\n");
+
+	if (flags & RV8803_FLAG_TF) {
+		flags &= ~RV8803_FLAG_TF;
+		rv8803->ctrl &= ~RV8803_CTRL_TIE;
+		events |= RTC_PF;
+	}
+
+	if (flags & RV8803_FLAG_AF) {
+		flags &= ~RV8803_FLAG_AF;
+		rv8803->ctrl &= ~RV8803_CTRL_AIE;
+		events |= RTC_AF;
+	}
+
+	if (flags & RV8803_FLAG_UF) {
+		flags &= ~RV8803_FLAG_UF;
+		rv8803->ctrl &= ~RV8803_CTRL_UIE;
+		events |= RTC_UF;
+	}
+
+	if (events) {
+		rtc_update_irq(rv8803->rtc, 1, events);
+		i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+		i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
+					  rv8803->ctrl);
+	}
+
+	spin_unlock(&rv8803->flags_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
+{
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+	u8 date1[7];
+	u8 date2[7];
+	u8 *date = date1;
+	int ret, flags;
+
+	flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+	if (flags < 0)
+		return flags;
+
+	if (flags & RV8803_FLAG_V2F) {
+		dev_warn(dev, "Voltage low, data is invalid.\n");
+		return -EINVAL;
+	}
+
+	ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
+					    7, date);
+	if (ret != 7)
+		return ret < 0 ? ret : -EIO;
+
+	if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) {
+		ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
+						    7, date2);
+		if (ret != 7)
+			return ret < 0 ? ret : -EIO;
+
+		if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59))
+			date = date2;
+	}
+
+	tm->tm_sec  = bcd2bin(date[RV8803_SEC] & 0x7f);
+	tm->tm_min  = bcd2bin(date[RV8803_MIN] & 0x7f);
+	tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f);
+	tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f);
+	tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f);
+	tm->tm_mon  = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1;
+	tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100;
+
+	return rtc_valid_tm(tm);
+}
+
+static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+	u8 date[7];
+	int flags, ret;
+	unsigned long irqflags;
+
+	if ((tm->tm_year < 100) || (tm->tm_year > 199))
+		return -EINVAL;
+
+	date[RV8803_SEC]   = bin2bcd(tm->tm_sec);
+	date[RV8803_MIN]   = bin2bcd(tm->tm_min);
+	date[RV8803_HOUR]  = bin2bcd(tm->tm_hour);
+	date[RV8803_WEEK]  = 1 << (tm->tm_wday);
+	date[RV8803_DAY]   = bin2bcd(tm->tm_mday);
+	date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1);
+	date[RV8803_YEAR]  = bin2bcd(tm->tm_year - 100);
+
+	ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC,
+					     7, date);
+	if (ret < 0)
+		return ret;
+
+	spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+
+	flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+	if (flags < 0) {
+		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		return flags;
+	}
+
+	ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
+					flags & ~RV8803_FLAG_V2F);
+
+	spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+
+	return ret;
+}
+
+static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+	struct i2c_client *client = rv8803->client;
+	u8 alarmvals[3];
+	int flags, ret;
+
+	ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN,
+					    3, alarmvals);
+	if (ret != 3)
+		return ret < 0 ? ret : -EIO;
+
+	flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+	if (flags < 0)
+		return flags;
+
+	alrm->time.tm_sec  = 0;
+	alrm->time.tm_min  = bcd2bin(alarmvals[0] & 0x7f);
+	alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
+	alrm->time.tm_wday = -1;
+	alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
+	alrm->time.tm_mon  = -1;
+	alrm->time.tm_year = -1;
+
+	alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
+	alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
+
+	return 0;
+}
+
+static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+	u8 alarmvals[3];
+	u8 ctrl[2];
+	int ret, err;
+	unsigned long irqflags;
+
+	/* The alarm has no seconds, round up to nearest minute */
+	if (alrm->time.tm_sec) {
+		time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
+
+		alarm_time += 60 - alrm->time.tm_sec;
+		rtc_time64_to_tm(alarm_time, &alrm->time);
+	}
+
+	spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+
+	ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
+	if (ret != 2) {
+		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		return ret < 0 ? ret : -EIO;
+	}
+
+	alarmvals[0] = bin2bcd(alrm->time.tm_min);
+	alarmvals[1] = bin2bcd(alrm->time.tm_hour);
+	alarmvals[2] = bin2bcd(alrm->time.tm_mday);
+
+	if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) {
+		rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE);
+		err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
+						rv8803->ctrl);
+		if (err) {
+			spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+			return err;
+		}
+	}
+
+	ctrl[1] &= ~RV8803_FLAG_AF;
+	err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
+	spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+	if (err)
+		return err;
+
+	err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN,
+					     3, alarmvals);
+	if (err)
+		return err;
+
+	if (alrm->enabled) {
+		if (rv8803->rtc->uie_rtctimer.enabled)
+			rv8803->ctrl |= RV8803_CTRL_UIE;
+		if (rv8803->rtc->aie_timer.enabled)
+			rv8803->ctrl |= RV8803_CTRL_AIE;
+
+		err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
+						rv8803->ctrl);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+	int ctrl, flags, err;
+	unsigned long irqflags;
+
+	ctrl = rv8803->ctrl;
+
+	if (enabled) {
+		if (rv8803->rtc->uie_rtctimer.enabled)
+			ctrl |= RV8803_CTRL_UIE;
+		if (rv8803->rtc->aie_timer.enabled)
+			ctrl |= RV8803_CTRL_AIE;
+	} else {
+		if (!rv8803->rtc->uie_rtctimer.enabled)
+			ctrl &= ~RV8803_CTRL_UIE;
+		if (!rv8803->rtc->aie_timer.enabled)
+			ctrl &= ~RV8803_CTRL_AIE;
+	}
+
+	spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+	flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+	if (flags < 0) {
+		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		return flags;
+	}
+	flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
+	err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+	spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+	if (err)
+		return err;
+
+	if (ctrl != rv8803->ctrl) {
+		rv8803->ctrl = ctrl;
+		err = i2c_smbus_write_byte_data(client, RV8803_CTRL,
+						rv8803->ctrl);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+	int flags, ret = 0;
+	unsigned long irqflags;
+
+	switch (cmd) {
+	case RTC_VL_READ:
+		flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+		if (flags < 0)
+			return flags;
+
+		if (flags & RV8803_FLAG_V1F)
+			dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
+
+		if (flags & RV8803_FLAG_V2F)
+			dev_warn(&client->dev, "Voltage low, data loss detected.\n");
+
+		flags &= RV8803_FLAG_V1F | RV8803_FLAG_V2F;
+
+		if (copy_to_user((void __user *)arg, &flags, sizeof(int)))
+			return -EFAULT;
+
+		return 0;
+
+	case RTC_VL_CLR:
+		spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+		flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+		if (flags < 0) {
+			spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+			return flags;
+		}
+
+		flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
+		ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		if (ret < 0)
+			return ret;
+
+		return 0;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
+				  struct bin_attribute *attr,
+				  char *buf, loff_t off, size_t count)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]);
+	if (ret < 0)
+		return ret;
+
+	return 1;
+}
+
+static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *attr,
+				 char *buf, loff_t off, size_t count)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, RV8803_RAM);
+	if (ret < 0)
+		return ret;
+
+	buf[0] = ret;
+
+	return 1;
+}
+
+static struct bin_attribute rv8803_nvram_attr = {
+	.attr = {
+		.name = "nvram",
+		.mode = S_IRUGO | S_IWUSR,
+	},
+	.size = 1,
+	.read = rv8803_nvram_read,
+	.write = rv8803_nvram_write,
+};
+
+static struct rtc_class_ops rv8803_rtc_ops = {
+	.read_time = rv8803_get_time,
+	.set_time = rv8803_set_time,
+	.ioctl = rv8803_ioctl,
+};
+
+static int rv8803_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct rv8803_data *rv8803;
+	int err, flags;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_I2C_BLOCK)) {
+		dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
+		return -EIO;
+	}
+
+	rv8803 = devm_kzalloc(&client->dev, sizeof(struct rv8803_data),
+			      GFP_KERNEL);
+	if (!rv8803)
+		return -ENOMEM;
+
+	rv8803->client = client;
+	i2c_set_clientdata(client, rv8803);
+
+	flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+	if (flags < 0)
+		return flags;
+
+	if (flags & RV8803_FLAG_V1F)
+		dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
+
+	if (flags & RV8803_FLAG_V2F)
+		dev_warn(&client->dev, "Voltage low, data loss detected.\n");
+
+	if (flags & RV8803_FLAG_AF)
+		dev_warn(&client->dev, "An alarm maybe have been missed.\n");
+
+	if (client->irq > 0) {
+		err = devm_request_threaded_irq(&client->dev, client->irq,
+						NULL, rv8803_handle_irq,
+						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+						"rv8803", client);
+		if (err) {
+			dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
+			client->irq = 0;
+		} else {
+			rv8803_rtc_ops.read_alarm = rv8803_get_alarm;
+			rv8803_rtc_ops.set_alarm = rv8803_set_alarm;
+			rv8803_rtc_ops.alarm_irq_enable = rv8803_alarm_irq_enable;
+		}
+	}
+
+	rv8803->rtc = devm_rtc_device_register(&client->dev, client->name,
+					       &rv8803_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rv8803->rtc)) {
+		dev_err(&client->dev, "unable to register the class device\n");
+		return PTR_ERR(rv8803->rtc);
+	}
+
+	err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
+					RV8803_EXT_WADA);
+	if (err)
+		return err;
+
+	err = device_create_bin_file(&client->dev, &rv8803_nvram_attr);
+	if (err)
+		return err;
+
+	rv8803->rtc->max_user_freq = 1;
+
+	return 0;
+}
+
+static int rv8803_remove(struct i2c_client *client)
+{
+	device_remove_bin_file(&client->dev, &rv8803_nvram_attr);
+
+	return 0;
+}
+
+static const struct i2c_device_id rv8803_id[] = {
+	{ "rv8803", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rv8803_id);
+
+static struct i2c_driver rv8803_driver = {
+	.driver = {
+		.name = "rtc-rv8803",
+	},
+	.probe		= rv8803_probe,
+	.remove		= rv8803_remove,
+	.id_table	= rv8803_id,
+};
+module_i2c_driver(rv8803_driver);
+
+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
+MODULE_DESCRIPTION("Micro Crystal RV8803 RTC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 24c3d69ce1b9..bd911bafb809 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -65,6 +65,7 @@
 
 static const struct i2c_device_id rx8025_id[] = {
 	{ "rx8025", 0 },
+	{ "rv8803", 1 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, rx8025_id);
@@ -518,9 +519,8 @@ static int rx8025_probe(struct i2c_client *client,
 	}
 
 	rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
-	if (!rx8025) {
+	if (!rx8025)
 		return -ENOMEM;
-	}
 
 	rx8025->client = client;
 	i2c_set_clientdata(client, rx8025);
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 7cc8f73a3fe8..ffb860d18701 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -302,6 +302,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	struct s3c_rtc *info = dev_get_drvdata(dev);
 	struct rtc_time *tm = &alrm->time;
 	unsigned int alrm_en;
+	int year = tm->tm_year - 100;
 
 	dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
 		 alrm->enabled,
@@ -328,6 +329,21 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 		writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
 	}
 
+	if (year < 100 && year >= 0) {
+		alrm_en |= S3C2410_RTCALM_YEAREN;
+		writeb(bin2bcd(year), info->base + S3C2410_ALMYEAR);
+	}
+
+	if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
+		alrm_en |= S3C2410_RTCALM_MONEN;
+		writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
+	}
+
+	if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
+		alrm_en |= S3C2410_RTCALM_DAYEN;
+		writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE);
+	}
+
 	dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
 
 	writeb(alrm_en, info->base + S3C2410_RTCALM);
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index eb09eddf39b8..ca54d039da31 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -32,8 +32,6 @@
 #include <linux/stmp3xxx_rtc_wdt.h>
 
 #define STMP3XXX_RTC_CTRL			0x0
-#define STMP3XXX_RTC_CTRL_SET			0x4
-#define STMP3XXX_RTC_CTRL_CLR			0x8
 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN		0x00000001
 #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002
 #define STMP3XXX_RTC_CTRL_ALARM_IRQ		0x00000004
@@ -52,8 +50,6 @@
 #define STMP3XXX_RTC_WATCHDOG			0x50
 
 #define STMP3XXX_RTC_PERSISTENT0		0x60
-#define STMP3XXX_RTC_PERSISTENT0_SET		0x64
-#define STMP3XXX_RTC_PERSISTENT0_CLR		0x68
 #define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN		(1 << 2)
@@ -179,7 +175,7 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
 
 	if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
 		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
-				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
 		rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
 		return IRQ_HANDLED;
 	}
@@ -194,15 +190,17 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	if (enabled) {
 		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
-				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+				STMP_OFFSET_REG_SET);
 		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-				rtc_data->io + STMP3XXX_RTC_CTRL_SET);
+			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
 	} else {
 		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
-				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+				STMP_OFFSET_REG_CLR);
 		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
 	}
 	return 0;
 }
@@ -245,7 +243,7 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
 		return 0;
 
 	writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+		rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
 
 	return 0;
 }
@@ -334,16 +332,17 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
 	}
 
-	writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+	writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+			STMP_OFFSET_REG_SET);
 
 	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr,
-			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+		rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
 
 	writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
 			STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+		rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
 
 	rtc_data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				&stmp3xxx_rtc_ops, THIS_MODULE);
@@ -376,7 +375,7 @@ static int stmp3xxx_rtc_resume(struct device *dev)
 	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
-			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+		rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
 	return 0;
 }
 #endif
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index d80ae852334d..624bce51b27d 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
 	/* Turn on update interrupts (one per second) */
 	retval = ioctl(fd, RTC_UIE_ON, 0);
 	if (retval == -1) {
-		if (errno == ENOTTY) {
+		if (errno == EINVAL) {
 			fprintf(stderr,
 				"\n...Update IRQs not supported.\n");
 			goto test_READ;