Linux RTC
 help / color / mirror / Atom feed
* [PATCH 11/11] rtc: ds1307: remove ds1307_remove
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

ds1307_remove() is now empty, remove it

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-ds1307.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 6f91c11a5f03..ea83ddc5a513 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -1701,11 +1701,6 @@ static int ds1307_probe(struct i2c_client *client,
 	return err;
 }
 
-static int ds1307_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
 static struct i2c_driver ds1307_driver = {
 	.driver = {
 		.name	= "rtc-ds1307",
@@ -1713,7 +1708,6 @@ static struct i2c_driver ds1307_driver = {
 		.acpi_match_table = ACPI_PTR(ds1307_acpi_ids),
 	},
 	.probe		= ds1307_probe,
-	.remove		= ds1307_remove,
 	.id_table	= ds1307_id,
 };
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH 05/11] rtc: add generic nvmem support
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

Many RTCs have an on board non volatile storage. It can be battery backed
RAM or an EEPROM. Use the nvmem subsystem to export it to both userspace
and in-kernel consumers.

This stays compatible with the previous (non documented) ABI that was using
/sys/class/rtc/rtcx/device/nvram to export that memory. But will warn about
the deprecation.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 Documentation/rtc.txt  |   2 +
 drivers/rtc/Kconfig    |   8 ++++
 drivers/rtc/Makefile   |   1 +
 drivers/rtc/class.c    |   4 ++
 drivers/rtc/nvmem.c    | 113 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/rtc/rtc-core.h |   8 ++++
 include/linux/rtc.h    |   7 +++
 7 files changed, 143 insertions(+)
 create mode 100644 drivers/rtc/nvmem.c

diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 47feb4414b7e..c0c977445fb9 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -164,6 +164,8 @@ offset		 The amount which the rtc clock has been adjusted in firmware.
 		 which are added to or removed from the rtc's base clock per
 		 billion ticks. A positive value makes a day pass more slowly,
 		 longer, and a negative value makes a day pass more quickly.
+*/nvmem		 The non volatile storage exported as a raw file, as described
+		 in Documentation/nvmem/nvmem.txt
 ================ ==============================================================
 
 IOCTL interface
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index d0e4b4a1c2a1..72419ac2c52a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -77,6 +77,14 @@ config RTC_DEBUG
 	  Say yes here to enable debugging support in the RTC framework
 	  and individual RTC drivers.
 
+config RTC_NVMEM
+	bool "RTC non volatile storage support"
+	select NVMEM
+	default RTC_CLASS
+	help
+	  Say yes here to add support for the non volatile (often battery
+	  backed) storage present on RTCs.
+
 comment "RTC interfaces"
 
 config RTC_INTF_SYSFS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 4050fc8b9271..acd366b41c85 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -15,6 +15,7 @@ ifdef CONFIG_RTC_DRV_EFI
 rtc-core-y			+= rtc-efi-platform.o
 endif
 
+rtc-core-$(CONFIG_RTC_NVMEM)		+= nvmem.o
 rtc-core-$(CONFIG_RTC_INTF_DEV)		+= rtc-dev.o
 rtc-core-$(CONFIG_RTC_INTF_PROC)	+= rtc-proc.o
 rtc-core-$(CONFIG_RTC_INTF_SYSFS)	+= rtc-sysfs.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 58e2a05765bb..2ed970d61da1 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -290,6 +290,8 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
  */
 void rtc_device_unregister(struct rtc_device *rtc)
 {
+	rtc_nvmem_unregister(rtc);
+
 	mutex_lock(&rtc->ops_lock);
 	/*
 	 * Remove innards of this RTC, then disable it, before
@@ -448,6 +450,8 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
 
 	rtc_proc_add_device(rtc);
 
+	rtc_nvmem_register(rtc);
+
 	rtc->registered = true;
 	dev_info(rtc->dev.parent, "registered as %s\n",
 		 dev_name(&rtc->dev));
diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c
new file mode 100644
index 000000000000..8567b4ed9ac6
--- /dev/null
+++ b/drivers/rtc/nvmem.c
@@ -0,0 +1,113 @@
+/*
+ * RTC subsystem, nvmem interface
+ *
+ * Copyright (C) 2017 Alexandre Belloni
+ *
+ * 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/err.h>
+#include <linux/types.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/rtc.h>
+#include <linux/sysfs.h>
+
+#include "rtc-core.h"
+
+/*
+ * Deprecated ABI compatibility, this should be removed at some point
+ */
+
+static const char nvram_warning[] = "Deprecated ABI, please use nvmem";
+
+static ssize_t
+rtc_nvram_read(struct file *filp, struct kobject *kobj,
+	       struct bin_attribute *attr,
+	       char *buf, loff_t off, size_t count)
+{
+	struct rtc_device *rtc = attr->private;
+
+	dev_warn_once(kobj_to_dev(kobj), nvram_warning);
+
+	return nvmem_device_read(rtc->nvmem, off, count, buf);
+}
+
+static ssize_t
+rtc_nvram_write(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct rtc_device *rtc = attr->private;
+
+	dev_warn_once(kobj_to_dev(kobj), nvram_warning);
+
+	return nvmem_device_write(rtc->nvmem, off, count, buf);
+}
+
+static int rtc_nvram_register(struct rtc_device *rtc)
+{
+	int err;
+
+	rtc->nvram = devm_kzalloc(rtc->dev.parent,
+				sizeof(struct bin_attribute),
+				GFP_KERNEL);
+	if (!rtc->nvram)
+		return -ENOMEM;
+
+	rtc->nvram->attr.name = "nvram";
+	rtc->nvram->attr.mode = 0644;
+	rtc->nvram->private = rtc;
+
+	sysfs_bin_attr_init(rtc->nvram);
+
+	rtc->nvram->read = rtc_nvram_read;
+	rtc->nvram->write = rtc_nvram_write;
+	rtc->nvram->size = rtc->nvmem_config->size;
+
+	err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
+				    rtc->nvram);
+	if (err) {
+		devm_kfree(rtc->dev.parent, rtc->nvram);
+		rtc->nvram = NULL;
+	}
+
+	return err;
+}
+
+static void rtc_nvram_unregister(struct rtc_device *rtc)
+{
+	sysfs_remove_bin_file(&rtc->dev.parent->kobj, rtc->nvram);
+}
+
+/*
+ * New ABI, uses nvmem
+ */
+void rtc_nvmem_register(struct rtc_device *rtc)
+{
+	if (!rtc->nvmem_config)
+		return;
+
+	rtc->nvmem_config->dev = &rtc->dev;
+	rtc->nvmem_config->owner = rtc->owner;
+	rtc->nvmem = nvmem_register(rtc->nvmem_config);
+	if (IS_ERR_OR_NULL(rtc->nvmem))
+		return;
+
+	/* Register the old ABI */
+	if (rtc->nvram_old_abi)
+		rtc_nvram_register(rtc);
+}
+
+void rtc_nvmem_unregister(struct rtc_device *rtc)
+{
+	if (IS_ERR_OR_NULL(rtc->nvmem))
+		return;
+
+	/* unregister the old ABI */
+	if (rtc->nvram)
+		rtc_nvram_unregister(rtc);
+
+	nvmem_unregister(rtc->nvmem);
+}
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
index 7a4ed2f7c7d7..ecab76a3207c 100644
--- a/drivers/rtc/rtc-core.h
+++ b/drivers/rtc/rtc-core.h
@@ -45,3 +45,11 @@ static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
 	return NULL;
 }
 #endif
+
+#ifdef CONFIG_RTC_NVMEM
+void rtc_nvmem_register(struct rtc_device *rtc);
+void rtc_nvmem_unregister(struct rtc_device *rtc);
+#else
+static inline void rtc_nvmem_register(struct rtc_device *rtc) {}
+static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {}
+#endif
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 8e4a5f44f59e..d53ecdc060cf 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/nvmem-provider.h>
 #include <uapi/linux/rtc.h>
 
 extern int rtc_month_days(unsigned int month, unsigned int year);
@@ -144,6 +145,12 @@ struct rtc_device {
 
 	bool registered;
 
+	struct nvmem_config *nvmem_config;
+	struct nvmem_device *nvmem;
+	/* Old ABI support */
+	bool nvram_old_abi;
+	struct bin_attribute *nvram;
+
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
 	struct work_struct uie_task;
 	struct timer_list uie_timer;
-- 
2.11.0

^ permalink raw reply related

* [PATCH 08/11] rtc: rv8803: remove rv8803_remove
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

rv8803_remove() is now empty, remove it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-rv8803.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 10474ab7887d..aae2576741a6 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -612,11 +612,6 @@ static int rv8803_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int rv8803_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
 static const struct i2c_device_id rv8803_id[] = {
 	{ "rv8803", rv_8803 },
 	{ "rx8900", rx_8900 },
@@ -643,7 +638,6 @@ static struct i2c_driver rv8803_driver = {
 		.of_match_table = of_match_ptr(rv8803_of_match),
 	},
 	.probe		= rv8803_probe,
-	.remove		= rv8803_remove,
 	.id_table	= rv8803_id,
 };
 module_i2c_driver(rv8803_driver);
-- 
2.11.0

^ permalink raw reply related

* [PATCH 09/11] rtc: ds1307: switch to rtc_register_device
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

This removes a possible race condition and crash and allows for further
improvement of the driver.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-ds1307.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 43e9dc6f2edc..bac920a50ece 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -1663,8 +1663,8 @@ static int ds1307_probe(struct i2c_client *client,
 		device_set_wakeup_capable(ds1307->dev, true);
 		set_bit(HAS_ALARM, &ds1307->flags);
 	}
-	ds1307->rtc = devm_rtc_device_register(ds1307->dev, ds1307->name,
-				rtc_ops, THIS_MODULE);
+
+	ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
 	if (IS_ERR(ds1307->rtc)) {
 		return PTR_ERR(ds1307->rtc);
 	}
@@ -1726,6 +1726,11 @@ static int ds1307_probe(struct i2c_client *client,
 		}
 	}
 
+	ds1307->rtc->ops = rtc_ops;
+	err = rtc_register_device(ds1307->rtc);
+	if (err)
+		return err;
+
 	ds1307_hwmon_register(ds1307);
 	ds1307_clks_register(ds1307);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH 00/11] RTC: rework registration
From: Alexandre Belloni @ 2017-07-06  9:41 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

There are multiple race condition issues in the RTC drivers. It is
especially apparent in the IRQ handling and additionnal sysfs attributes
registration.

To solve most of those and allow to extend the framework more easily,
introduce a new registration method that allows to first allocate an
rtc_device and then register it.

Also, introduce a generic way to register nvmem devices so RTCs can
export their non volatile storage.

One of the goal will be to get rid of the IS_ERR_OR_NULL(rtc) check in
rtc_update_irq which makes people assume everything is properly handled
in the core.

Alexandre Belloni (11):
  rtc: class separate device allocation from registration
  rtc: class separate id allocation from registration
  rtc: introduce new registration method
  rtc: at91rm9200: remove race condition
  rtc: add generic nvmem support
  rtc: rv8803: switch to rtc_register_device
  rtc: rv8803: use generic nvmem support
  rtc: rv8803: remove rv8803_remove
  rtc: ds1307: switch to rtc_register_device
  rtc: ds1307: use generic nvmem
  rtc: ds1307: remove ds1307_remove

 Documentation/rtc.txt        |   2 +
 drivers/rtc/Kconfig          |   8 ++
 drivers/rtc/Makefile         |   1 +
 drivers/rtc/class.c          | 195 +++++++++++++++++++++++++++++++++----------
 drivers/rtc/nvmem.c          | 113 +++++++++++++++++++++++++
 drivers/rtc/rtc-at91rm9200.c |  14 ++--
 drivers/rtc/rtc-core.h       |   8 ++
 drivers/rtc/rtc-ds1307.c     | 103 +++++++----------------
 drivers/rtc/rtc-rv8803.c     |  72 +++++++---------
 include/linux/rtc.h          |  14 ++++
 10 files changed, 362 insertions(+), 168 deletions(-)
 create mode 100644 drivers/rtc/nvmem.c

-- 
2.11.0

^ permalink raw reply

* [PATCH 10/11] rtc: ds1307: use generic nvmem
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

Instead of adding a binary sysfs attribute from the driver (which suffers
from a race condition as the attribute appears after the device), use the
core to register an nvmem device.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-ds1307.c | 88 ++++++++++++------------------------------------
 1 file changed, 22 insertions(+), 66 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index bac920a50ece..6f91c11a5f03 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -117,7 +117,7 @@ struct ds1307 {
 	u8			offset; /* register's offset */
 	u8			regs[11];
 	u16			nvram_offset;
-	struct bin_attribute	*nvram;
+	struct nvmem_config	nvmem_cfg;
 	enum ds_type		type;
 	unsigned long		flags;
 #define HAS_NVRAM	0		/* bit 0 == sysfs file active */
@@ -885,43 +885,24 @@ static const struct rtc_class_ops mcp794xx_rtc_ops = {
 
 /*----------------------------------------------------------------------*/
 
-static ssize_t
-ds1307_nvram_read(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
+static int ds1307_nvram_read(void *priv, unsigned int offset, void *val,
+			     size_t bytes)
 {
-	struct ds1307		*ds1307;
-	int			result;
-
-	ds1307 = dev_get_drvdata(kobj_to_dev(kobj));
+	struct ds1307 *ds1307 = priv;
 
-	result = regmap_bulk_read(ds1307->regmap, ds1307->nvram_offset + off,
-				  buf, count);
-	if (result)
-		dev_err(ds1307->dev, "%s error %d\n", "nvram read", result);
-	return result;
+	return regmap_bulk_read(ds1307->regmap, ds1307->nvram_offset + offset,
+				val, bytes);
 }
 
-static ssize_t
-ds1307_nvram_write(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
+static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
+			      size_t bytes)
 {
-	struct ds1307		*ds1307;
-	int			result;
+	struct ds1307 *ds1307 = priv;
 
-	ds1307 = dev_get_drvdata(kobj_to_dev(kobj));
-
-	result = regmap_bulk_write(ds1307->regmap, ds1307->nvram_offset + off,
-				   buf, count);
-	if (result) {
-		dev_err(ds1307->dev, "%s error %d\n", "nvram write", result);
-		return result;
-	}
-	return count;
+	return regmap_bulk_write(ds1307->regmap, ds1307->nvram_offset + offset,
+				 val, bytes);
 }
 
-
 /*----------------------------------------------------------------------*/
 
 static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307,
@@ -1693,37 +1674,17 @@ static int ds1307_probe(struct i2c_client *client,
 	}
 
 	if (chip->nvram_size) {
-
-		ds1307->nvram = devm_kzalloc(ds1307->dev,
-					sizeof(struct bin_attribute),
-					GFP_KERNEL);
-		if (!ds1307->nvram) {
-			dev_err(ds1307->dev,
-				"cannot allocate memory for nvram sysfs\n");
-		} else {
-
-			ds1307->nvram->attr.name = "nvram";
-			ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
-
-			sysfs_bin_attr_init(ds1307->nvram);
-
-			ds1307->nvram->read = ds1307_nvram_read;
-			ds1307->nvram->write = ds1307_nvram_write;
-			ds1307->nvram->size = chip->nvram_size;
-			ds1307->nvram_offset = chip->nvram_offset;
-
-			err = sysfs_create_bin_file(&ds1307->dev->kobj,
-						    ds1307->nvram);
-			if (err) {
-				dev_err(ds1307->dev,
-					"unable to create sysfs file: %s\n",
-					ds1307->nvram->attr.name);
-			} else {
-				set_bit(HAS_NVRAM, &ds1307->flags);
-				dev_info(ds1307->dev, "%zu bytes nvram\n",
-					 ds1307->nvram->size);
-			}
-		}
+		ds1307->nvmem_cfg.name = "ds1307_nvram";
+		ds1307->nvmem_cfg.word_size = 1;
+		ds1307->nvmem_cfg.stride = 1;
+		ds1307->nvmem_cfg.size = chip->nvram_size;
+		ds1307->nvmem_cfg.reg_read = ds1307_nvram_read;
+		ds1307->nvmem_cfg.reg_write = ds1307_nvram_write;
+		ds1307->nvmem_cfg.priv = ds1307;
+		ds1307->nvram_offset = chip->nvram_offset;
+
+		ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg;
+		ds1307->rtc->nvram_old_abi = true;
 	}
 
 	ds1307->rtc->ops = rtc_ops;
@@ -1742,11 +1703,6 @@ static int ds1307_probe(struct i2c_client *client,
 
 static int ds1307_remove(struct i2c_client *client)
 {
-	struct ds1307 *ds1307 = i2c_get_clientdata(client);
-
-	if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
-		sysfs_remove_bin_file(&ds1307->dev->kobj, ds1307->nvram);
-
 	return 0;
 }
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH 06/11] rtc: rv8803: switch to rtc_register_device
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

This removes a possible race condition and allows for further improvement
of the driver.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-rv8803.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 9ad97ab29866..209edbb03971 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -577,6 +577,11 @@ static int rv8803_probe(struct i2c_client *client,
 	if (flags & RV8803_FLAG_AF)
 		dev_warn(&client->dev, "An alarm maybe have been missed.\n");
 
+	rv8803->rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(rv8803->rtc)) {
+		return PTR_ERR(rv8803->rtc);
+	}
+
 	if (client->irq > 0) {
 		err = devm_request_threaded_irq(&client->dev, client->irq,
 						NULL, rv8803_handle_irq,
@@ -592,12 +597,10 @@ static int rv8803_probe(struct i2c_client *client,
 		}
 	}
 
-	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);
-	}
+	rv8803->rtc->ops = &rv8803_rtc_ops;
+	err = rtc_register_device(rv8803->rtc);
+	if (err)
+		return err;
 
 	err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
 	if (err)
-- 
2.11.0

^ permalink raw reply related

* [PATCH 07/11] rtc: rv8803: use generic nvmem support
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

Instead of adding a binary sysfs attribute from the driver (which suffers
from a race condition as the attribute appears after the device), use the
core to register an nvmem device.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-rv8803.c | 51 +++++++++++++++++++-----------------------------
 1 file changed, 20 insertions(+), 31 deletions(-)

diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 209edbb03971..10474ab7887d 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -68,6 +68,7 @@ struct rv8803_data {
 	struct mutex flags_lock;
 	u8 ctrl;
 	enum rv8803_type type;
+	struct nvmem_config nvmem_cfg;
 };
 
 static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
@@ -460,48 +461,32 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 	}
 }
 
-static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
-				  struct bin_attribute *attr,
-				  char *buf, loff_t off, size_t count)
+static int rv8803_nvram_write(void *priv, unsigned int offset, void *val,
+			      size_t bytes)
 {
-	struct device *dev = kobj_to_dev(kobj);
-	struct i2c_client *client = to_i2c_client(dev);
 	int ret;
 
-	ret = rv8803_write_reg(client, RV8803_RAM, buf[0]);
+	ret = rv8803_write_reg(priv, RV8803_RAM, *(u8 *)val);
 	if (ret)
 		return ret;
 
-	return 1;
+	return 0;
 }
 
-static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
-				 struct bin_attribute *attr,
-				 char *buf, loff_t off, size_t count)
+static int rv8803_nvram_read(void *priv, unsigned int offset,
+			     void *val, size_t bytes)
 {
-	struct device *dev = kobj_to_dev(kobj);
-	struct i2c_client *client = to_i2c_client(dev);
 	int ret;
 
-	ret = rv8803_read_reg(client, RV8803_RAM);
+	ret = rv8803_read_reg(priv, RV8803_RAM);
 	if (ret < 0)
 		return ret;
 
-	buf[0] = ret;
+	*(u8 *)val = ret;
 
-	return 1;
+	return 0;
 }
 
-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,
@@ -597,7 +582,17 @@ static int rv8803_probe(struct i2c_client *client,
 		}
 	}
 
+	rv8803->nvmem_cfg.name = "rv8803_nvram",
+	rv8803->nvmem_cfg.word_size = 1,
+	rv8803->nvmem_cfg.stride = 1,
+	rv8803->nvmem_cfg.size = 1,
+	rv8803->nvmem_cfg.reg_read = rv8803_nvram_read,
+	rv8803->nvmem_cfg.reg_write = rv8803_nvram_write,
+	rv8803->nvmem_cfg.priv = client;
+
 	rv8803->rtc->ops = &rv8803_rtc_ops;
+	rv8803->rtc->nvmem_config = &rv8803->nvmem_cfg;
+	rv8803->rtc->nvram_old_abi = true;
 	err = rtc_register_device(rv8803->rtc);
 	if (err)
 		return err;
@@ -612,10 +607,6 @@ static int rv8803_probe(struct i2c_client *client,
 		return err;
 	}
 
-	err = device_create_bin_file(&client->dev, &rv8803_nvram_attr);
-	if (err)
-		return err;
-
 	rv8803->rtc->max_user_freq = 1;
 
 	return 0;
@@ -623,8 +614,6 @@ static int rv8803_probe(struct i2c_client *client,
 
 static int rv8803_remove(struct i2c_client *client)
 {
-	device_remove_bin_file(&client->dev, &rv8803_nvram_attr);
-
 	return 0;
 }
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH 03/11] rtc: introduce new registration method
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

Introduce rtc_register_device() to register an already allocated and
initialized struct rtc_device. It automatically sets up the owner and the
two steps allocation/registration will allow to remove race conditions in
the IRQ handling of some driver. It also allows to properly extend the core
without adding more arguments to rtc_device_register().

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/class.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/rtc.h |  7 +++++
 2 files changed, 91 insertions(+)

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 93ce88e1b1cb..58e2a05765bb 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -150,6 +150,7 @@ static SIMPLE_DEV_PM_OPS(rtc_class_dev_pm_ops, rtc_suspend, rtc_resume);
 #define RTC_CLASS_DEV_PM_OPS	NULL
 #endif
 
+/* Ensure the caller will set the id before releasing the device */
 static struct rtc_device *rtc_allocate_device(void)
 {
 	struct rtc_device *rtc;
@@ -372,6 +373,89 @@ void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc)
 }
 EXPORT_SYMBOL_GPL(devm_rtc_device_unregister);
 
+static void devm_rtc_release_device(struct device *dev, void *res)
+{
+	struct rtc_device *rtc = *(struct rtc_device **)res;
+
+	if (rtc->registered)
+		rtc_device_unregister(rtc);
+	else
+		put_device(&rtc->dev);
+}
+
+struct rtc_device *devm_rtc_allocate_device(struct device *dev)
+{
+	struct rtc_device **ptr, *rtc;
+	int id, err;
+
+	id = rtc_device_get_id(dev);
+	if (id < 0)
+		return ERR_PTR(id);
+
+	ptr = devres_alloc(devm_rtc_release_device, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr) {
+		err = -ENOMEM;
+		goto exit_ida;
+	}
+
+	rtc = rtc_allocate_device();
+	if (!rtc) {
+		err = -ENOMEM;
+		goto exit_devres;
+	}
+
+	*ptr = rtc;
+	devres_add(dev, ptr);
+
+	rtc->id = id;
+	rtc->dev.parent = dev;
+	dev_set_name(&rtc->dev, "rtc%d", id);
+
+	return rtc;
+
+exit_devres:
+	devres_free(ptr);
+exit_ida:
+	ida_simple_remove(&rtc_ida, id);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(devm_rtc_allocate_device);
+
+int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
+{
+	struct rtc_wkalrm alrm;
+	int err;
+
+	if (!rtc->ops)
+		return -EINVAL;
+
+	rtc->owner = owner;
+
+	/* Check to see if there is an ALARM already set in hw */
+	err = __rtc_read_alarm(rtc, &alrm);
+	if (!err && !rtc_valid_tm(&alrm.time))
+		rtc_initialize_alarm(rtc, &alrm);
+
+	rtc_dev_prepare(rtc);
+
+	err = cdev_device_add(&rtc->char_dev, &rtc->dev);
+	if (err)
+		dev_warn(rtc->dev.parent, "failed to add char device %d:%d\n",
+			 MAJOR(rtc->dev.devt), rtc->id);
+	else
+		dev_dbg(rtc->dev.parent, "char device (%d:%d)\n",
+			MAJOR(rtc->dev.devt), rtc->id);
+
+	rtc_proc_add_device(rtc);
+
+	rtc->registered = true;
+	dev_info(rtc->dev.parent, "registered as %s\n",
+		 dev_name(&rtc->dev));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__rtc_register_device);
+
 static int __init rtc_init(void)
 {
 	rtc_class = class_create(THIS_MODULE, "rtc");
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index d354f56e0cf5..8e4a5f44f59e 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -142,6 +142,8 @@ struct rtc_device {
 	/* Some hardware can't support UIE mode */
 	int uie_unsupported;
 
+	bool registered;
+
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
 	struct work_struct uie_task;
 	struct timer_list uie_timer;
@@ -163,6 +165,8 @@ extern struct rtc_device *devm_rtc_device_register(struct device *dev,
 					const char *name,
 					const struct rtc_class_ops *ops,
 					struct module *owner);
+struct rtc_device *devm_rtc_allocate_device(struct device *dev);
+int __rtc_register_device(struct module *owner, struct rtc_device *rtc);
 extern void rtc_device_unregister(struct rtc_device *rtc);
 extern void devm_rtc_device_unregister(struct device *dev,
 					struct rtc_device *rtc);
@@ -218,6 +222,9 @@ static inline bool is_leap_year(unsigned int year)
 	return (!(year % 4) && (year % 100)) || !(year % 400);
 }
 
+#define rtc_register_device(device) \
+	__rtc_register_device(THIS_MODULE, device)
+
 #ifdef CONFIG_RTC_HCTOSYS_DEVICE
 extern int rtc_hctosys_ret;
 #else
-- 
2.11.0

^ permalink raw reply related

* [PATCH 04/11] rtc: at91rm9200: remove race condition
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

While highly unlikely, it is possible to get an interrupt as soon as it is
requested. In that case, at91_rtc_interrupt() will be called with rtc ==
NULL.

Solve that by using devm_rtc_allocate_device/rtc_register_device.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/rtc-at91rm9200.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index b60fd477778f..e221b78b6f10 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -409,6 +409,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+	platform_set_drvdata(pdev, rtc);
+
 	sclk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(sclk))
 		return PTR_ERR(sclk);
@@ -441,13 +446,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
 	if (!device_can_wakeup(&pdev->dev))
 		device_init_wakeup(&pdev->dev, 1);
 
-	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
-				&at91_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
+	rtc->ops = &at91_rtc_ops;
+	ret = rtc_register_device(rtc);
+	if (ret)
 		goto err_clk;
-	}
-	platform_set_drvdata(pdev, rtc);
 
 	/* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy
 	 * completion.
-- 
2.11.0

^ permalink raw reply related

* [PATCH 02/11] rtc: class separate id allocation from registration
From: Alexandre Belloni @ 2017-07-06  9:41 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

Create rtc_device_get_id to allocate the id for an RTC.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/class.c | 44 +++++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index fb39c1334d7b..93ce88e1b1cb 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -186,6 +186,27 @@ static struct rtc_device *rtc_allocate_device(void)
 	return rtc;
 }
 
+static int rtc_device_get_id(struct device *dev)
+{
+	int of_id = -1, id = -1;
+
+	if (dev->of_node)
+		of_id = of_alias_get_id(dev->of_node, "rtc");
+	else if (dev->parent && dev->parent->of_node)
+		of_id = of_alias_get_id(dev->parent->of_node, "rtc");
+
+	if (of_id >= 0) {
+		id = ida_simple_get(&rtc_ida, of_id, of_id + 1, GFP_KERNEL);
+		if (id < 0)
+			dev_warn(dev, "/aliases ID %d not available\n", of_id);
+	}
+
+	if (id < 0)
+		id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL);
+
+	return id;
+}
+
 /**
  * rtc_device_register - register w/ RTC class
  * @dev: the device to register
@@ -201,27 +222,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 {
 	struct rtc_device *rtc;
 	struct rtc_wkalrm alrm;
-	int of_id = -1, id = -1, err;
-
-	if (dev->of_node)
-		of_id = of_alias_get_id(dev->of_node, "rtc");
-	else if (dev->parent && dev->parent->of_node)
-		of_id = of_alias_get_id(dev->parent->of_node, "rtc");
-
-	if (of_id >= 0) {
-		id = ida_simple_get(&rtc_ida, of_id, of_id + 1,
-				    GFP_KERNEL);
-		if (id < 0)
-			dev_warn(dev, "/aliases ID %d not available\n",
-				    of_id);
-	}
+	int id, err;
 
+	id = rtc_device_get_id(dev);
 	if (id < 0) {
-		id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL);
-		if (id < 0) {
-			err = id;
-			goto exit;
-		}
+		err = id;
+		goto exit;
 	}
 
 	rtc = rtc_allocate_device();
-- 
2.11.0

^ permalink raw reply related

* [PATCH 01/11] rtc: class separate device allocation from registration
From: Alexandre Belloni @ 2017-07-06  9:41 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni
In-Reply-To: <20170706094208.16240-1-alexandre.belloni@free-electrons.com>

Create rtc_allocate_device to allocate memory for a struct rtc_device and
initialize it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/rtc/class.c | 63 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 37 insertions(+), 26 deletions(-)

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 543c64cd3df0..fb39c1334d7b 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -150,6 +150,41 @@ static SIMPLE_DEV_PM_OPS(rtc_class_dev_pm_ops, rtc_suspend, rtc_resume);
 #define RTC_CLASS_DEV_PM_OPS	NULL
 #endif
 
+static struct rtc_device *rtc_allocate_device(void)
+{
+	struct rtc_device *rtc;
+
+	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return NULL;
+
+	device_initialize(&rtc->dev);
+
+	rtc->irq_freq = 1;
+	rtc->max_user_freq = 64;
+	rtc->dev.class = rtc_class;
+	rtc->dev.groups = rtc_get_dev_attribute_groups();
+	rtc->dev.release = rtc_device_release;
+
+	mutex_init(&rtc->ops_lock);
+	spin_lock_init(&rtc->irq_lock);
+	spin_lock_init(&rtc->irq_task_lock);
+	init_waitqueue_head(&rtc->irq_queue);
+
+	/* Init timerqueue */
+	timerqueue_init_head(&rtc->timerqueue);
+	INIT_WORK(&rtc->irqwork, rtc_timer_do_work);
+	/* Init aie timer */
+	rtc_timer_init(&rtc->aie_timer, rtc_aie_update_irq, (void *)rtc);
+	/* Init uie timer */
+	rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, (void *)rtc);
+	/* Init pie timer */
+	hrtimer_init(&rtc->pie_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	rtc->pie_timer.function = rtc_pie_update_irq;
+	rtc->pie_enabled = 0;
+
+	return rtc;
+}
 
 /**
  * rtc_device_register - register w/ RTC class
@@ -189,40 +224,16 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 		}
 	}
 
-	rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
-	if (rtc == NULL) {
+	rtc = rtc_allocate_device();
+	if (!rtc) {
 		err = -ENOMEM;
 		goto exit_ida;
 	}
 
-	device_initialize(&rtc->dev);
-
 	rtc->id = id;
 	rtc->ops = ops;
 	rtc->owner = owner;
-	rtc->irq_freq = 1;
-	rtc->max_user_freq = 64;
 	rtc->dev.parent = dev;
-	rtc->dev.class = rtc_class;
-	rtc->dev.groups = rtc_get_dev_attribute_groups();
-	rtc->dev.release = rtc_device_release;
-
-	mutex_init(&rtc->ops_lock);
-	spin_lock_init(&rtc->irq_lock);
-	spin_lock_init(&rtc->irq_task_lock);
-	init_waitqueue_head(&rtc->irq_queue);
-
-	/* Init timerqueue */
-	timerqueue_init_head(&rtc->timerqueue);
-	INIT_WORK(&rtc->irqwork, rtc_timer_do_work);
-	/* Init aie timer */
-	rtc_timer_init(&rtc->aie_timer, rtc_aie_update_irq, (void *)rtc);
-	/* Init uie timer */
-	rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, (void *)rtc);
-	/* Init pie timer */
-	hrtimer_init(&rtc->pie_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	rtc->pie_timer.function = rtc_pie_update_irq;
-	rtc->pie_enabled = 0;
 
 	dev_set_name(&rtc->dev, "rtc%d", id);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCHv2 1/2] dt-bindings: rtc: stm32: add support for STM32H7
From: Amelie Delaunay @ 2017-07-06  8:47 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
	Maxime Coquelin, Alexandre Torgue
  Cc: rtc-linux, devicetree, linux-arm-kernel, linux-kernel,
	Amelie Delaunay
In-Reply-To: <1499330865-17232-1-git-send-email-amelie.delaunay@st.com>

This patch documents support for STM32H7 Real Time Clock.
It introduces a new compatible and rework clock definitions.
On STM32H7 we have a 'pclk' clock for register access, in addition to
the 'rtc_ck' clock.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
 .../devicetree/bindings/rtc/st,stm32-rtc.txt       | 32 ++++++++++++++++++----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
index e2837b9..0a4c371 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
@@ -1,17 +1,25 @@
 STM32 Real Time Clock
 
 Required properties:
-- compatible: "st,stm32-rtc".
+- compatible: can be either "st,stm32-rtc" or "st,stm32h7-rtc", depending on
+  the device is compatible with stm32(f4/f7) or stm32h7.
 - reg: address range of rtc register set.
-- clocks: reference to the clock entry ck_rtc.
+- clocks: can use up to two clocks, depending on part used:
+  - "rtc_ck": RTC clock source.
+    It is required on stm32(f4/f7) and stm32h7.
+  - "pclk": RTC APB interface clock.
+    It is not present on stm32(f4/f7).
+    It is required on stm32h7.
+- clock-names: must be "rtc_ck" and "pclk".
+    It is required only on stm32h7.
 - interrupt-parent: phandle for the interrupt controller.
 - interrupts: rtc alarm interrupt.
 - st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
   (RTC registers) write protection.
 
-Optional properties (to override default ck_rtc parent clock):
-- assigned-clocks: reference to the ck_rtc clock entry.
-- assigned-clock-parents: phandle of the new parent clock of ck_rtc.
+Optional properties (to override default rtc_ck parent clock):
+- assigned-clocks: reference to the rtc_ck clock entry.
+- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
 
 Example:
 
@@ -25,3 +33,17 @@ Example:
 		interrupts = <17 1>;
 		st,syscfg = <&pwrcfg>;
 	};
+
+	rtc: rtc@58004000 {
+		compatible = "st,stm32h7-rtc";
+		reg = <0x58004000 0x400>;
+		clocks = <&rcc RTCAPB_CK>, <&rcc RTC_CK>;
+		clock-names = "pclk", "rtc_ck";
+		assigned-clocks = <&rcc RTC_CK>;
+		assigned-clock-parents = <&rcc LSE_CK>;
+		interrupt-parent = <&exti>;
+		interrupts = <17 1>;
+		interrupt-names = "alarm";
+		st,syscfg = <&pwrcfg>;
+		status = "disabled";
+	};
-- 
1.9.1

^ permalink raw reply related

* [PATCHv2 2/2] rtc: stm32: add STM32H7 RTC support
From: Amelie Delaunay @ 2017-07-06  8:47 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
	Maxime Coquelin, Alexandre Torgue
  Cc: rtc-linux, devicetree, linux-arm-kernel, linux-kernel,
	Amelie Delaunay
In-Reply-To: <1499330865-17232-1-git-send-email-amelie.delaunay@st.com>

This patch adds support for STM32H7 RTC. On STM32H7, the RTC bus interface
clock (APB clock) needs to be enabled.

Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
 drivers/rtc/rtc-stm32.c | 82 +++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 65 insertions(+), 17 deletions(-)

diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index bd57eb1..3a5c3d7 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -94,11 +94,17 @@
 /* STM32_PWR_CR bit field */
 #define PWR_CR_DBP			BIT(8)
 
+struct stm32_rtc_data {
+	bool has_pclk;
+};
+
 struct stm32_rtc {
 	struct rtc_device *rtc_dev;
 	void __iomem *base;
 	struct regmap *dbp;
-	struct clk *ck_rtc;
+	struct stm32_rtc_data *data;
+	struct clk *pclk;
+	struct clk *rtc_ck;
 	int irq_alarm;
 };
 
@@ -122,9 +128,9 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
 		writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
 
 		/*
-		 * It takes around 2 ck_rtc clock cycles to enter in
+		 * It takes around 2 rtc_ck clock cycles to enter in
 		 * initialization phase mode (and have INITF flag set). As
-		 * slowest ck_rtc frequency may be 32kHz and highest should be
+		 * slowest rtc_ck frequency may be 32kHz and highest should be
 		 * 1MHz, we poll every 10 us with a timeout of 100ms.
 		 */
 		return readl_relaxed_poll_timeout_atomic(
@@ -153,7 +159,7 @@ static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
 
 	/*
 	 * Wait for RSF to be set to ensure the calendar registers are
-	 * synchronised, it takes around 2 ck_rtc clock cycles
+	 * synchronised, it takes around 2 rtc_ck clock cycles
 	 */
 	return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
 						 isr,
@@ -456,7 +462,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 	/*
 	 * Poll Alarm write flag to be sure that Alarm update is allowed: it
-	 * takes around 2 ck_rtc clock cycles
+	 * takes around 2 rtc_ck clock cycles
 	 */
 	ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
 						isr,
@@ -490,8 +496,17 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	.alarm_irq_enable = stm32_rtc_alarm_irq_enable,
 };
 
+static const struct stm32_rtc_data stm32_rtc_data = {
+	.has_pclk = false,
+};
+
+static const struct stm32_rtc_data stm32h7_rtc_data = {
+	.has_pclk = true,
+};
+
 static const struct of_device_id stm32_rtc_of_match[] = {
-	{ .compatible = "st,stm32-rtc" },
+	{ .compatible = "st,stm32-rtc", .data = &stm32_rtc_data },
+	{ .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data },
 	{}
 };
 MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
@@ -503,7 +518,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
 	unsigned int rate;
 	int ret = 0;
 
-	rate = clk_get_rate(rtc->ck_rtc);
+	rate = clk_get_rate(rtc->rtc_ck);
 
 	/* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
 	pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
@@ -524,7 +539,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
 		pred_a = pred_a_max;
 		pred_s = (rate / (pred_a + 1)) - 1;
 
-		dev_warn(&pdev->dev, "ck_rtc is %s\n",
+		dev_warn(&pdev->dev, "rtc_ck is %s\n",
 			 (rate < ((pred_a + 1) * (pred_s + 1))) ?
 			 "fast" : "slow");
 	}
@@ -561,6 +576,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 {
 	struct stm32_rtc *rtc;
 	struct resource *res;
+	const struct of_device_id *match;
 	int ret;
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -579,15 +595,34 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 		return PTR_ERR(rtc->dbp);
 	}
 
-	rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(rtc->ck_rtc)) {
-		dev_err(&pdev->dev, "no ck_rtc clock");
-		return PTR_ERR(rtc->ck_rtc);
+	match = of_match_device(stm32_rtc_of_match, &pdev->dev);
+	rtc->data = (struct stm32_rtc_data *)match->data;
+
+	if (!rtc->data->has_pclk) {
+		rtc->pclk = NULL;
+		rtc->rtc_ck = devm_clk_get(&pdev->dev, NULL);
+	} else {
+		rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
+		if (IS_ERR(rtc->pclk)) {
+			dev_err(&pdev->dev, "no pclk clock");
+			return PTR_ERR(rtc->pclk);
+		}
+		rtc->rtc_ck = devm_clk_get(&pdev->dev, "rtc_ck");
+	}
+	if (IS_ERR(rtc->rtc_ck)) {
+		dev_err(&pdev->dev, "no rtc_ck clock");
+		return PTR_ERR(rtc->rtc_ck);
+	}
+
+	if (rtc->data->has_pclk) {
+		ret = clk_prepare_enable(rtc->pclk);
+		if (ret)
+			return ret;
 	}
 
-	ret = clk_prepare_enable(rtc->ck_rtc);
+	ret = clk_prepare_enable(rtc->rtc_ck);
 	if (ret)
-		return ret;
+		goto err;
 
 	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
 
@@ -595,7 +630,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 	 * After a system reset, RTC_ISR.INITS flag can be read to check if
 	 * the calendar has been initalized or not. INITS flag is reset by a
 	 * power-on reset (no vbat, no power-supply). It is not reset if
-	 * ck_rtc parent clock has changed (so RTC prescalers need to be
+	 * rtc_ck parent clock has changed (so RTC prescalers need to be
 	 * changed). That's why we cannot rely on this flag to know if RTC
 	 * init has to be done.
 	 */
@@ -646,7 +681,9 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 
 	return 0;
 err:
-	clk_disable_unprepare(rtc->ck_rtc);
+	if (rtc->data->has_pclk)
+		clk_disable_unprepare(rtc->pclk);
+	clk_disable_unprepare(rtc->rtc_ck);
 
 	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
 
@@ -667,7 +704,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
 	writel_relaxed(cr, rtc->base + STM32_RTC_CR);
 	stm32_rtc_wpr_lock(rtc);
 
-	clk_disable_unprepare(rtc->ck_rtc);
+	clk_disable_unprepare(rtc->rtc_ck);
+	if (rtc->data->has_pclk)
+		clk_disable_unprepare(rtc->pclk);
 
 	/* Enable backup domain write protection */
 	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
@@ -682,6 +721,9 @@ static int stm32_rtc_suspend(struct device *dev)
 {
 	struct stm32_rtc *rtc = dev_get_drvdata(dev);
 
+	if (rtc->data->has_pclk)
+		clk_disable_unprepare(rtc->pclk);
+
 	if (device_may_wakeup(dev))
 		return enable_irq_wake(rtc->irq_alarm);
 
@@ -693,6 +735,12 @@ static int stm32_rtc_resume(struct device *dev)
 	struct stm32_rtc *rtc = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (rtc->data->has_pclk) {
+		ret = clk_prepare_enable(rtc->pclk);
+		if (ret)
+			return ret;
+	}
+
 	ret = stm32_rtc_wait_sync(rtc);
 	if (ret < 0)
 		return ret;
-- 
1.9.1

^ permalink raw reply related

* [rtc-linux] [PATCHv2 2/2] rtc: stm32: add STM32H7 RTC support
From: Amelie Delaunay @ 2017-07-06  8:47 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
	Maxime Coquelin, Alexandre Torgue
  Cc: rtc-linux, devicetree, linux-arm-kernel, linux-kernel,
	Amelie Delaunay
In-Reply-To: <1499330865-17232-1-git-send-email-amelie.delaunay@st.com>

This patch adds support for STM32H7 RTC. On STM32H7, the RTC bus interface
clock (APB clock) needs to be enabled.

Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
 drivers/rtc/rtc-stm32.c | 82 +++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 65 insertions(+), 17 deletions(-)

diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index bd57eb1..3a5c3d7 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -94,11 +94,17 @@
 /* STM32_PWR_CR bit field */
 #define PWR_CR_DBP			BIT(8)
 
+struct stm32_rtc_data {
+	bool has_pclk;
+};
+
 struct stm32_rtc {
 	struct rtc_device *rtc_dev;
 	void __iomem *base;
 	struct regmap *dbp;
-	struct clk *ck_rtc;
+	struct stm32_rtc_data *data;
+	struct clk *pclk;
+	struct clk *rtc_ck;
 	int irq_alarm;
 };
 
@@ -122,9 +128,9 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
 		writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
 
 		/*
-		 * It takes around 2 ck_rtc clock cycles to enter in
+		 * It takes around 2 rtc_ck clock cycles to enter in
 		 * initialization phase mode (and have INITF flag set). As
-		 * slowest ck_rtc frequency may be 32kHz and highest should be
+		 * slowest rtc_ck frequency may be 32kHz and highest should be
 		 * 1MHz, we poll every 10 us with a timeout of 100ms.
 		 */
 		return readl_relaxed_poll_timeout_atomic(
@@ -153,7 +159,7 @@ static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
 
 	/*
 	 * Wait for RSF to be set to ensure the calendar registers are
-	 * synchronised, it takes around 2 ck_rtc clock cycles
+	 * synchronised, it takes around 2 rtc_ck clock cycles
 	 */
 	return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
 						 isr,
@@ -456,7 +462,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 	/*
 	 * Poll Alarm write flag to be sure that Alarm update is allowed: it
-	 * takes around 2 ck_rtc clock cycles
+	 * takes around 2 rtc_ck clock cycles
 	 */
 	ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
 						isr,
@@ -490,8 +496,17 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	.alarm_irq_enable = stm32_rtc_alarm_irq_enable,
 };
 
+static const struct stm32_rtc_data stm32_rtc_data = {
+	.has_pclk = false,
+};
+
+static const struct stm32_rtc_data stm32h7_rtc_data = {
+	.has_pclk = true,
+};
+
 static const struct of_device_id stm32_rtc_of_match[] = {
-	{ .compatible = "st,stm32-rtc" },
+	{ .compatible = "st,stm32-rtc", .data = &stm32_rtc_data },
+	{ .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data },
 	{}
 };
 MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
@@ -503,7 +518,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
 	unsigned int rate;
 	int ret = 0;
 
-	rate = clk_get_rate(rtc->ck_rtc);
+	rate = clk_get_rate(rtc->rtc_ck);
 
 	/* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
 	pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
@@ -524,7 +539,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
 		pred_a = pred_a_max;
 		pred_s = (rate / (pred_a + 1)) - 1;
 
-		dev_warn(&pdev->dev, "ck_rtc is %s\n",
+		dev_warn(&pdev->dev, "rtc_ck is %s\n",
 			 (rate < ((pred_a + 1) * (pred_s + 1))) ?
 			 "fast" : "slow");
 	}
@@ -561,6 +576,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 {
 	struct stm32_rtc *rtc;
 	struct resource *res;
+	const struct of_device_id *match;
 	int ret;
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -579,15 +595,34 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 		return PTR_ERR(rtc->dbp);
 	}
 
-	rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(rtc->ck_rtc)) {
-		dev_err(&pdev->dev, "no ck_rtc clock");
-		return PTR_ERR(rtc->ck_rtc);
+	match = of_match_device(stm32_rtc_of_match, &pdev->dev);
+	rtc->data = (struct stm32_rtc_data *)match->data;
+
+	if (!rtc->data->has_pclk) {
+		rtc->pclk = NULL;
+		rtc->rtc_ck = devm_clk_get(&pdev->dev, NULL);
+	} else {
+		rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
+		if (IS_ERR(rtc->pclk)) {
+			dev_err(&pdev->dev, "no pclk clock");
+			return PTR_ERR(rtc->pclk);
+		}
+		rtc->rtc_ck = devm_clk_get(&pdev->dev, "rtc_ck");
+	}
+	if (IS_ERR(rtc->rtc_ck)) {
+		dev_err(&pdev->dev, "no rtc_ck clock");
+		return PTR_ERR(rtc->rtc_ck);
+	}
+
+	if (rtc->data->has_pclk) {
+		ret = clk_prepare_enable(rtc->pclk);
+		if (ret)
+			return ret;
 	}
 
-	ret = clk_prepare_enable(rtc->ck_rtc);
+	ret = clk_prepare_enable(rtc->rtc_ck);
 	if (ret)
-		return ret;
+		goto err;
 
 	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
 
@@ -595,7 +630,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 	 * After a system reset, RTC_ISR.INITS flag can be read to check if
 	 * the calendar has been initalized or not. INITS flag is reset by a
 	 * power-on reset (no vbat, no power-supply). It is not reset if
-	 * ck_rtc parent clock has changed (so RTC prescalers need to be
+	 * rtc_ck parent clock has changed (so RTC prescalers need to be
 	 * changed). That's why we cannot rely on this flag to know if RTC
 	 * init has to be done.
 	 */
@@ -646,7 +681,9 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 
 	return 0;
 err:
-	clk_disable_unprepare(rtc->ck_rtc);
+	if (rtc->data->has_pclk)
+		clk_disable_unprepare(rtc->pclk);
+	clk_disable_unprepare(rtc->rtc_ck);
 
 	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
 
@@ -667,7 +704,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
 	writel_relaxed(cr, rtc->base + STM32_RTC_CR);
 	stm32_rtc_wpr_lock(rtc);
 
-	clk_disable_unprepare(rtc->ck_rtc);
+	clk_disable_unprepare(rtc->rtc_ck);
+	if (rtc->data->has_pclk)
+		clk_disable_unprepare(rtc->pclk);
 
 	/* Enable backup domain write protection */
 	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
@@ -682,6 +721,9 @@ static int stm32_rtc_suspend(struct device *dev)
 {
 	struct stm32_rtc *rtc = dev_get_drvdata(dev);
 
+	if (rtc->data->has_pclk)
+		clk_disable_unprepare(rtc->pclk);
+
 	if (device_may_wakeup(dev))
 		return enable_irq_wake(rtc->irq_alarm);
 
@@ -693,6 +735,12 @@ static int stm32_rtc_resume(struct device *dev)
 	struct stm32_rtc *rtc = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (rtc->data->has_pclk) {
+		ret = clk_prepare_enable(rtc->pclk);
+		if (ret)
+			return ret;
+	}
+
 	ret = stm32_rtc_wait_sync(rtc);
 	if (ret < 0)
 		return ret;
-- 
1.9.1

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply related

* [rtc-linux] [PATCHv2 1/2] dt-bindings: rtc: stm32: add support for STM32H7
From: Amelie Delaunay @ 2017-07-06  8:47 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
	Maxime Coquelin, Alexandre Torgue
  Cc: rtc-linux, devicetree, linux-arm-kernel, linux-kernel,
	Amelie Delaunay
In-Reply-To: <1499330865-17232-1-git-send-email-amelie.delaunay@st.com>

This patch documents support for STM32H7 Real Time Clock.
It introduces a new compatible and rework clock definitions.
On STM32H7 we have a 'pclk' clock for register access, in addition to
the 'rtc_ck' clock.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
 .../devicetree/bindings/rtc/st,stm32-rtc.txt       | 32 ++++++++++++++++++----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
index e2837b9..0a4c371 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
@@ -1,17 +1,25 @@
 STM32 Real Time Clock
 
 Required properties:
-- compatible: "st,stm32-rtc".
+- compatible: can be either "st,stm32-rtc" or "st,stm32h7-rtc", depending on
+  the device is compatible with stm32(f4/f7) or stm32h7.
 - reg: address range of rtc register set.
-- clocks: reference to the clock entry ck_rtc.
+- clocks: can use up to two clocks, depending on part used:
+  - "rtc_ck": RTC clock source.
+    It is required on stm32(f4/f7) and stm32h7.
+  - "pclk": RTC APB interface clock.
+    It is not present on stm32(f4/f7).
+    It is required on stm32h7.
+- clock-names: must be "rtc_ck" and "pclk".
+    It is required only on stm32h7.
 - interrupt-parent: phandle for the interrupt controller.
 - interrupts: rtc alarm interrupt.
 - st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
   (RTC registers) write protection.
 
-Optional properties (to override default ck_rtc parent clock):
-- assigned-clocks: reference to the ck_rtc clock entry.
-- assigned-clock-parents: phandle of the new parent clock of ck_rtc.
+Optional properties (to override default rtc_ck parent clock):
+- assigned-clocks: reference to the rtc_ck clock entry.
+- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
 
 Example:
 
@@ -25,3 +33,17 @@ Example:
 		interrupts = <17 1>;
 		st,syscfg = <&pwrcfg>;
 	};
+
+	rtc: rtc@58004000 {
+		compatible = "st,stm32h7-rtc";
+		reg = <0x58004000 0x400>;
+		clocks = <&rcc RTCAPB_CK>, <&rcc RTC_CK>;
+		clock-names = "pclk", "rtc_ck";
+		assigned-clocks = <&rcc RTC_CK>;
+		assigned-clock-parents = <&rcc LSE_CK>;
+		interrupt-parent = <&exti>;
+		interrupts = <17 1>;
+		interrupt-names = "alarm";
+		st,syscfg = <&pwrcfg>;
+		status = "disabled";
+	};
-- 
1.9.1

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply related

* [PATCHv2 0/2] rtc: add support for STM32H7 RTC
From: Amelie Delaunay @ 2017-07-06  8:47 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
	Maxime Coquelin, Alexandre Torgue
  Cc: rtc-linux, devicetree, linux-arm-kernel, linux-kernel,
	Amelie Delaunay

Add support for STM32H7 Real Time Clock variant.
Difference is regarding clocks: there is a 'pclk' clock on STM32H7
for register access.

Amelie Delaunay (2):
  dt-bindings: rtc: stm32: add support for STM32H7
  rtc: stm32: add STM32H7 RTC support

 .../devicetree/bindings/rtc/st,stm32-rtc.txt       | 32 +++++++--
 drivers/rtc/rtc-stm32.c                            | 82 +++++++++++++++++-----
 2 files changed, 92 insertions(+), 22 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [rtc-linux] Re: [PATCH 2/2] rtc: stm32: add STM32H7 RTC support
From: Amelie DELAUNAY @ 2017-07-06  7:33 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Alessandro Zummo, Rob Herring, Mark Rutland, Maxime Coquelin,
	Alexandre Torgue, rtc-linux, devicetree, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20170705213746.6hf5af57ty6wsfgs@piout.net>

Hi,

On 07/05/2017 11:37 PM, Alexandre Belloni wrote:
> Hi,
> 
> This is mostly fine, even if I'm not too happy with the
> s/ck_rtc/rtc_ck/.
> 
This clock name has changed in datasheet between STM32F4/STM32F7 and 
STM32H7, so, I'm not really happy too... But, as there is only one clock 
on F4/F7, its name is not important for the end user. Now that pclk 
appears, we need to distinguish the two clocks, and for the end user, it 
is better if the clock names match the datasheet.

> On 26/06/2017 at 11:51:29 +0200, Amelie Delaunay wrote:
>> -	rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL);
>> -	if (IS_ERR(rtc->ck_rtc)) {
>> -		dev_err(&pdev->dev, "no ck_rtc clock");
>> -		return PTR_ERR(rtc->ck_rtc);
>> +	match = of_match_device(stm32_rtc_of_match, &pdev->dev);
>> +	if (match && match->data)
>> +		rtc->data = (struct stm32_rtc_data *)match->data;
>> +	else
>> +		return -EINVAL;
> 
> This will never happen, you can remove that test.
> 
> 
OK, will be done in V2.

Thanks for the review,
Amelie

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* [rtc-linux] Re: [PATCH 3/3] mfd: twl: move header file out of I2C realm
From: Lee Jones @ 2017-07-06  7:03 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Wolfram Sang, linux-i2c, Tony Lindgren, Russell King,
	Linus Walleij, Alexandre Courbot, Jonathan Cameron,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Dmitry Torokhov, Kishon Vijay Abraham I, Sebastian Reichel,
	Liam Girdwood, Mark Brown, Alessandro Zummo, Alexandre Belloni,
	Felipe Balbi, Greg Kroah-Hartman, Daniel Thompson, Jingoo Han,
	Bartlomiej Zolnierkiewicz, Wim Van Sebroeck, Guenter Roeck,
	Peter Ujfalusi, Jaroslav Kysela, Takashi Iwai, linux-omap,
	linux-arm-kernel, linux-kernel, linux-gpio, linux-iio,
	linux-input, linux-pm, linux-pwm, rtc-linux, linux-usb,
	linux-fbdev, linux-watchdog, alsa-devel
In-Reply-To: <20170706064453.GH16144@ulmo.fritz.box>

On Thu, 06 Jul 2017, Thierry Reding wrote:

> On Mon, May 22, 2017 at 12:02:10AM +0200, Wolfram Sang wrote:
> > include/linux/i2c is not for client devices. Move the header file to a
> > more appropriate location.
> >=20
> > Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
> > ---
> >  arch/arm/mach-omap2/common.h            | 2 +-
> >  arch/arm/mach-omap2/omap_twl.c          | 2 +-
> >  drivers/gpio/gpio-twl4030.c             | 2 +-
> >  drivers/iio/adc/twl4030-madc.c          | 2 +-
> >  drivers/iio/adc/twl6030-gpadc.c         | 2 +-
> >  drivers/input/keyboard/twl4030_keypad.c | 2 +-
> >  drivers/input/misc/twl4030-pwrbutton.c  | 2 +-
> >  drivers/input/misc/twl4030-vibra.c      | 2 +-
> >  drivers/mfd/twl-core.c                  | 6 +++---
> >  drivers/mfd/twl4030-audio.c             | 2 +-
> >  drivers/mfd/twl4030-irq.c               | 2 +-
> >  drivers/mfd/twl4030-power.c             | 2 +-
> >  drivers/mfd/twl6030-irq.c               | 2 +-
> >  drivers/phy/phy-twl4030-usb.c           | 2 +-
> >  drivers/power/supply/twl4030_charger.c  | 2 +-
> >  drivers/pwm/pwm-twl-led.c               | 2 +-
> >  drivers/pwm/pwm-twl.c                   | 2 +-
> >  drivers/regulator/twl-regulator.c       | 2 +-
> >  drivers/regulator/twl6030-regulator.c   | 2 +-
> >  drivers/rtc/rtc-twl.c                   | 2 +-
> >  drivers/usb/phy/phy-twl6030-usb.c       | 2 +-
> >  drivers/video/backlight/pandora_bl.c    | 2 +-
> >  drivers/watchdog/twl4030_wdt.c          | 2 +-
> >  include/linux/{i2c =3D> mfd}/twl.h        | 0
> >  sound/soc/codecs/twl4030.c              | 2 +-
> >  25 files changed, 26 insertions(+), 26 deletions(-)
> >  rename include/linux/{i2c =3D> mfd}/twl.h (100%)
>=20
> I didn't see this get applied yet, so just in case anyone was waiting
> for me (this is trivial, so I don't think there's a need):

You're not the last. :)

--=20
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org =E2=94=82 Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

--=20
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---=20
You received this message because you are subscribed to the Google Groups "=
rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* [rtc-linux] Re: [PATCH 3/3] mfd: twl: move header file out of I2C realm
From: Thierry Reding @ 2017-07-06  6:44 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linux-i2c, Tony Lindgren, Russell King, Linus Walleij,
	Alexandre Courbot, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Dmitry Torokhov,
	Lee Jones, Kishon Vijay Abraham I, Sebastian Reichel,
	Liam Girdwood, Mark Brown, Alessandro Zummo, Alexandre Belloni,
	Felipe Balbi, Greg Kroah-Hartman, Daniel Thompson, Jingoo Han,
	Bartlomiej Zolnierkiewicz, Wim Van Sebroeck, Guenter Roeck,
	Peter Ujfalusi, Jaroslav Kysela, Takashi Iwai, linux-omap,
	linux-arm-kernel, linux-kernel, linux-gpio, linux-iio,
	linux-input, linux-pm, linux-pwm, rtc-linux, linux-usb,
	linux-fbdev, linux-watchdog, alsa-devel
In-Reply-To: <20170521220212.1404-4-wsa@the-dreams.de>

[-- Attachment #1: Type: text/plain, Size: 2277 bytes --]

On Mon, May 22, 2017 at 12:02:10AM +0200, Wolfram Sang wrote:
> include/linux/i2c is not for client devices. Move the header file to a
> more appropriate location.
> 
> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
> ---
>  arch/arm/mach-omap2/common.h            | 2 +-
>  arch/arm/mach-omap2/omap_twl.c          | 2 +-
>  drivers/gpio/gpio-twl4030.c             | 2 +-
>  drivers/iio/adc/twl4030-madc.c          | 2 +-
>  drivers/iio/adc/twl6030-gpadc.c         | 2 +-
>  drivers/input/keyboard/twl4030_keypad.c | 2 +-
>  drivers/input/misc/twl4030-pwrbutton.c  | 2 +-
>  drivers/input/misc/twl4030-vibra.c      | 2 +-
>  drivers/mfd/twl-core.c                  | 6 +++---
>  drivers/mfd/twl4030-audio.c             | 2 +-
>  drivers/mfd/twl4030-irq.c               | 2 +-
>  drivers/mfd/twl4030-power.c             | 2 +-
>  drivers/mfd/twl6030-irq.c               | 2 +-
>  drivers/phy/phy-twl4030-usb.c           | 2 +-
>  drivers/power/supply/twl4030_charger.c  | 2 +-
>  drivers/pwm/pwm-twl-led.c               | 2 +-
>  drivers/pwm/pwm-twl.c                   | 2 +-
>  drivers/regulator/twl-regulator.c       | 2 +-
>  drivers/regulator/twl6030-regulator.c   | 2 +-
>  drivers/rtc/rtc-twl.c                   | 2 +-
>  drivers/usb/phy/phy-twl6030-usb.c       | 2 +-
>  drivers/video/backlight/pandora_bl.c    | 2 +-
>  drivers/watchdog/twl4030_wdt.c          | 2 +-
>  include/linux/{i2c => mfd}/twl.h        | 0
>  sound/soc/codecs/twl4030.c              | 2 +-
>  25 files changed, 26 insertions(+), 26 deletions(-)
>  rename include/linux/{i2c => mfd}/twl.h (100%)

I didn't see this get applied yet, so just in case anyone was waiting
for me (this is trivial, so I don't think there's a need):

Acked-by: Thierry Reding <thierry.reding@gmail.com>

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v2 02/10] MIPS: ranchu: Add Goldfish RTC driver
From: Alexandre Belloni @ 2017-07-05 21:56 UTC (permalink / raw)
  To: Aleksandar Markovic
  Cc: linux-mips, Aleksandar Markovic, Miodrag Dinic, Goran Ferenc,
	Alessandro Zummo, David S. Miller, Douglas Leung,
	Greg Kroah-Hartman, James Hogan, linux-kernel, linux-rtc,
	Martin K. Petersen, Mauro Carvalho Chehab, Paul Burton,
	Petar Jovanovic, Raghu Gandham
In-Reply-To: <1498664922-28493-3-git-send-email-aleksandar.markovic@rt-rk.com>

Hi,

The subject doesn't fit the subsystem style, this needs to be changed.

On 28/06/2017 at 17:46:55 +0200, Aleksandar Markovic wrote:
> From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
> 
> Add device driver for a virtual Goldfish RTC clock.
> 
> The driver can be built only if CONFIG_MIPS and CONFIG_GOLDFISH are
> set. The compatible string used by OS for binding the driver is
> defined as "google,goldfish-rtc".
> 

Is it really MIPS specific? I would expect the same driver to work on
the ARM based emulator too.

> +config RTC_DRV_GOLDFISH
> +	tristate "Goldfish Real Time Clock"
> +	depends on MIPS
> +	depends on GOLDFISH

This should be made buildable with COMPILE_TEST to extend coverage.

> +	help
> +	  Say yes here to build support for the Goldfish RTC.

Please, don't expect anybody to actually know what is goldfish can you
add a sentence or two?

> +static irqreturn_t goldfish_rtc_interrupt(int irq, void *dev_id)
> +{
> +	struct goldfish_rtc	*qrtc = dev_id;
> +	unsigned long		events = 0;
> +	void __iomem *base = qrtc->base;
> +
> +	writel(1, base + TIMER_CLEAR_INTERRUPT);
> +	events = RTC_IRQF | RTC_AF;
> +
> +	rtc_update_irq(qrtc->rtc, 1, events);

I'd say that events is not needed you can pass the flags directly to
rtc_update_irq

> +static int goldfish_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	u64 time;
> +	u64 time_low;
> +	u64 time_high;
> +	u64 time_high_prev;
> +
> +	struct goldfish_rtc *qrtc =
> +			platform_get_drvdata(to_platform_device(dev));
> +	void __iomem *base = qrtc->base;
> +
> +	time_high = readl(base + TIMER_TIME_HIGH);
> +	do {
> +		time_high_prev = time_high;
> +		time_low = readl(base + TIMER_TIME_LOW);
> +		time_high = readl(base + TIMER_TIME_HIGH);
> +	} while (time_high != time_high_prev);

I'm not sure why you need that loop as the comments for TIMER_TIME_LOW
and TIMER_TIME_HIGH indicate that TIMER_TIME_HIGH is latched when
TIMER_TIME_LOW is read. Note that the original driver from google
doesn't do that.

> +	time = (time_high << 32) | time_low;
> +
> +	do_div(time, NSEC_PER_SEC);
> +
> +	rtc_time_to_tm(time, tm);
> +
> +	return 0;
> +}
> +
> +static const struct rtc_class_ops goldfish_rtc_ops = {
> +	.read_time	= goldfish_rtc_read_time,
> +};
> +
> +static int goldfish_rtc_probe(struct platform_device *pdev)
> +{
> +	struct resource *r;
> +	struct goldfish_rtc *qrtc;
> +	unsigned long rtc_dev_len;
> +	unsigned long rtc_dev_addr;
> +	int err;
> +
> +	qrtc = devm_kzalloc(&pdev->dev, sizeof(*qrtc), GFP_KERNEL);
> +	if (qrtc == NULL)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, qrtc);
> +
> +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (r == NULL)
> +		return -ENODEV;
> +
> +	rtc_dev_addr = r->start;
> +	rtc_dev_len = resource_size(r);
> +	qrtc->base = devm_ioremap(&pdev->dev, rtc_dev_addr, rtc_dev_len);

devm_ioremap_resource ?

> +	if (IS_ERR(qrtc->base))
> +		return -ENODEV;
> +
> +	qrtc->irq = platform_get_irq(pdev, 0);
> +	if (qrtc->irq < 0)
> +		return -ENODEV;
> +

Is the irq so important that you have to fail here even if the driver
doesn't support any alarm?

> +	qrtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
> +					&goldfish_rtc_ops, THIS_MODULE);
> +	if (IS_ERR(qrtc->rtc))
> +		return PTR_ERR(qrtc->rtc);
> +
> +	err = devm_request_irq(&pdev->dev, qrtc->irq, goldfish_rtc_interrupt,
> +		0, pdev->name, qrtc);
> +	if (err)
> +		return err;

Ditto.


-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH] rtc: brcmstb-waketimer: fix settime function
From: Florian Fainelli @ 2017-07-05 21:52 UTC (permalink / raw)
  To: Alexandre Belloni, Arnd Bergmann
  Cc: Alessandro Zummo, Brian Norris, Gregory Fong,
	bcm-kernel-feedback-list, Markus Mayer, linux-rtc,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20170705211327.guccztud22hcmfjy@piout.net>

On 07/05/2017 02:13 PM, Alexandre Belloni wrote:
> Hi,
> 
> On 28/06/2017 at 22:07:34 +0200, Arnd Bergmann wrote:
>> gcc warns about an unused variable in the new driver:
>>
>> drivers/rtc/rtc-brcmstb-waketimer.c: In function 'brcmstb_waketmr_settime':
>> drivers/rtc/rtc-brcmstb-waketimer.c:142:6: error: unused variable 'ret' [-Werror=unused-variable]
>>
>> The same function also doesn't handle overflow correctly, this makes
>> it return -EINVAL when passed a time that doesn't fit within the
>> range of the register.
>>
>> Fixes: 9f4ad359c801 ("rtc: brcmstb-waketimer: Add Broadcom STB wake-timer")
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>> ---
>>  drivers/rtc/rtc-brcmstb-waketimer.c | 19 ++++++++++++-------
>>  1 file changed, 12 insertions(+), 7 deletions(-)
>>
> 
> I've squashed it in the original commit, I hope this is fine for you.

Works for me, thanks Alexandre!
-- 
Florian

^ permalink raw reply

* [rtc-linux] Re: [PATCH 2/2] rtc: stm32: add STM32H7 RTC support
From: Alexandre Belloni @ 2017-07-05 21:37 UTC (permalink / raw)
  To: Amelie Delaunay
  Cc: Alessandro Zummo, Rob Herring, Mark Rutland, Maxime Coquelin,
	Alexandre Torgue, rtc-linux, devicetree, linux-arm-kernel,
	linux-kernel
In-Reply-To: <1498470689-26829-3-git-send-email-amelie.delaunay@st.com>

Hi,

This is mostly fine, even if I'm not too happy with the
s/ck_rtc/rtc_ck/.

On 26/06/2017 at 11:51:29 +0200, Amelie Delaunay wrote:
> -	rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(rtc->ck_rtc)) {
> -		dev_err(&pdev->dev, "no ck_rtc clock");
> -		return PTR_ERR(rtc->ck_rtc);
> +	match = of_match_device(stm32_rtc_of_match, &pdev->dev);
> +	if (match && match->data)
> +		rtc->data = (struct stm32_rtc_data *)match->data;
> +	else
> +		return -EINVAL;

This will never happen, you can remove that test.


-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* Re: [PATCH v3] rtc: ds3232: add temperature support
From: Alexandre Belloni @ 2017-07-05 21:19 UTC (permalink / raw)
  To: Kirill Esipov; +Cc: a.zummo, linux-rtc, linux-kernel
In-Reply-To: <1498649349-4793-1-git-send-email-yesipov@gmail.com>

On 28/06/2017 at 14:29:09 +0300, Kirill Esipov wrote:
> DS3232/DS3234 has the temperature registers with a resolution of 0.25
> degree celsius. This enables to get the value through hwmon.
> 
> 	# cat /sys/class/hwmon/hwmon0/temp1_input
> 	37250
> 
> Signed-off-by: Kirill Esipov <yesipov@gmail.com>
> ---
>  drivers/rtc/Kconfig      |   8 ++++
>  drivers/rtc/rtc-ds3232.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 127 insertions(+)
> 
Applied, thanks.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH] rtc: brcmstb-waketimer: fix settime function
From: Alexandre Belloni @ 2017-07-05 21:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Alessandro Zummo, Brian Norris, Gregory Fong, Florian Fainelli,
	bcm-kernel-feedback-list, Markus Mayer, linux-rtc,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20170628200839.3114345-1-arnd@arndb.de>

Hi,

On 28/06/2017 at 22:07:34 +0200, Arnd Bergmann wrote:
> gcc warns about an unused variable in the new driver:
> 
> drivers/rtc/rtc-brcmstb-waketimer.c: In function 'brcmstb_waketmr_settime':
> drivers/rtc/rtc-brcmstb-waketimer.c:142:6: error: unused variable 'ret' [-Werror=unused-variable]
> 
> The same function also doesn't handle overflow correctly, this makes
> it return -EINVAL when passed a time that doesn't fit within the
> range of the register.
> 
> Fixes: 9f4ad359c801 ("rtc: brcmstb-waketimer: Add Broadcom STB wake-timer")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/rtc/rtc-brcmstb-waketimer.c | 19 ++++++++++++-------
>  1 file changed, 12 insertions(+), 7 deletions(-)
> 

I've squashed it in the original commit, I hope this is fine for you.

> diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
> index 5dea6d0627d8..796ac792a381 100644
> --- a/drivers/rtc/rtc-brcmstb-waketimer.c
> +++ b/drivers/rtc/rtc-brcmstb-waketimer.c
> @@ -138,10 +138,12 @@ static int brcmstb_waketmr_settime(struct device *dev,
>  				   struct rtc_time *tm)
>  {
>  	struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
> -	unsigned long sec;
> -	int ret;
> +	time64_t sec;
> +
> +	sec = rtc_tm_to_time64(tm);
>  
> -	rtc_tm_to_time(tm, &sec);
> +	if (sec > U32_MAX || sec < 0)
> +		return -EINVAL;
>  
>  	writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER);
>  
> @@ -152,14 +154,14 @@ static int brcmstb_waketmr_getalarm(struct device *dev,
>  				    struct rtc_wkalrm *alarm)
>  {
>  	struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
> -	unsigned long sec;
> +	time64_t sec;
>  	u32 reg;
>  
>  	sec = readl_relaxed(timer->base + BRCMSTB_WKTMR_ALARM);
>  	if (sec != 0) {
>  		/* Alarm is enabled */
>  		alarm->enabled = 1;
> -		rtc_time_to_tm(sec, &alarm->time);
> +		rtc_time64_to_tm(sec, &alarm->time);
>  	}
>  
>  	reg = readl_relaxed(timer->base + BRCMSTB_WKTMR_EVENT);
> @@ -172,13 +174,16 @@ static int brcmstb_waketmr_setalarm(struct device *dev,
>  				     struct rtc_wkalrm *alarm)
>  {
>  	struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
> -	unsigned long sec;
> +	time64_t sec;
>  
>  	if (alarm->enabled)
> -		rtc_tm_to_time(&alarm->time, &sec);
> +		sec = rtc_tm_to_time64(&alarm->time);
>  	else
>  		sec = 0;
>  
> +	if (sec > U32_MAX || sec < 0)
> +		return -EINVAL;
> +
>  	brcmstb_waketmr_set_alarm(timer, sec);
>  
>  	return 0;
> -- 
> 2.9.0
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox