linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] RTC: rework registration
@ 2017-07-06  9:41 Alexandre Belloni
  2017-07-06  9:41 ` [PATCH 01/11] rtc: class separate device allocation from registration Alexandre Belloni
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
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	[flat|nested] 12+ messages in thread

* [PATCH 01/11] rtc: class separate device allocation from registration
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
@ 2017-07-06  9:41 ` Alexandre Belloni
  2017-07-06  9:41 ` [PATCH 02/11] rtc: class separate id " Alexandre Belloni
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:41 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 02/11] rtc: class separate id allocation from registration
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
  2017-07-06  9:41 ` [PATCH 01/11] rtc: class separate device allocation from registration Alexandre Belloni
@ 2017-07-06  9:41 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 03/11] rtc: introduce new registration method Alexandre Belloni
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:41 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 03/11] rtc: introduce new registration method
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
  2017-07-06  9:41 ` [PATCH 01/11] rtc: class separate device allocation from registration Alexandre Belloni
  2017-07-06  9:41 ` [PATCH 02/11] rtc: class separate id " Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 04/11] rtc: at91rm9200: remove race condition Alexandre Belloni
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 04/11] rtc: at91rm9200: remove race condition
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (2 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 03/11] rtc: introduce new registration method Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 05/11] rtc: add generic nvmem support Alexandre Belloni
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 05/11] rtc: add generic nvmem support
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (3 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 04/11] rtc: at91rm9200: remove race condition Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 06/11] rtc: rv8803: switch to rtc_register_device Alexandre Belloni
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 06/11] rtc: rv8803: switch to rtc_register_device
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (4 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 05/11] rtc: add generic nvmem support Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 07/11] rtc: rv8803: use generic nvmem support Alexandre Belloni
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 07/11] rtc: rv8803: use generic nvmem support
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (5 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 06/11] rtc: rv8803: switch to rtc_register_device Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 08/11] rtc: rv8803: remove rv8803_remove Alexandre Belloni
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 08/11] rtc: rv8803: remove rv8803_remove
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (6 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 07/11] rtc: rv8803: use generic nvmem support Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 09/11] rtc: ds1307: switch to rtc_register_device Alexandre Belloni
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 09/11] rtc: ds1307: switch to rtc_register_device
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (7 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 08/11] rtc: rv8803: remove rv8803_remove Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 10/11] rtc: ds1307: use generic nvmem Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 11/11] rtc: ds1307: remove ds1307_remove Alexandre Belloni
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 10/11] rtc: ds1307: use generic nvmem
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (8 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 09/11] rtc: ds1307: switch to rtc_register_device Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  2017-07-06  9:42 ` [PATCH 11/11] rtc: ds1307: remove ds1307_remove Alexandre Belloni
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

* [PATCH 11/11] rtc: ds1307: remove ds1307_remove
  2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
                   ` (9 preceding siblings ...)
  2017-07-06  9:42 ` [PATCH 10/11] rtc: ds1307: use generic nvmem Alexandre Belloni
@ 2017-07-06  9:42 ` Alexandre Belloni
  10 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2017-07-06  9:42 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

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	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-07-06  9:45 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-06  9:41 [PATCH 00/11] RTC: rework registration Alexandre Belloni
2017-07-06  9:41 ` [PATCH 01/11] rtc: class separate device allocation from registration Alexandre Belloni
2017-07-06  9:41 ` [PATCH 02/11] rtc: class separate id " Alexandre Belloni
2017-07-06  9:42 ` [PATCH 03/11] rtc: introduce new registration method Alexandre Belloni
2017-07-06  9:42 ` [PATCH 04/11] rtc: at91rm9200: remove race condition Alexandre Belloni
2017-07-06  9:42 ` [PATCH 05/11] rtc: add generic nvmem support Alexandre Belloni
2017-07-06  9:42 ` [PATCH 06/11] rtc: rv8803: switch to rtc_register_device Alexandre Belloni
2017-07-06  9:42 ` [PATCH 07/11] rtc: rv8803: use generic nvmem support Alexandre Belloni
2017-07-06  9:42 ` [PATCH 08/11] rtc: rv8803: remove rv8803_remove Alexandre Belloni
2017-07-06  9:42 ` [PATCH 09/11] rtc: ds1307: switch to rtc_register_device Alexandre Belloni
2017-07-06  9:42 ` [PATCH 10/11] rtc: ds1307: use generic nvmem Alexandre Belloni
2017-07-06  9:42 ` [PATCH 11/11] rtc: ds1307: remove ds1307_remove Alexandre Belloni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).