[PATCH v3 4/4] rtc: ds1307: change nvram handling to use the nvmem subsystem
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: 2017-06-05 15:57:55
Subsystem:
real time clock (rtc) subsystem, the rest · Maintainers:
Alexandre Belloni, Linus Torvalds
The open coded handling of attribute nvram is from 2007 when the nvmem subsystem obviously didn't exist yet. Now we can use nvmem to simplify the driver. A side effect is that attribute nvram is replaced. New location is: /sys/bus/nvmem/devices/ds1307_nvram0/nvmem This might break user space applications. However attribute nvram is nowhere officially documented and I'm not sure whether anybody is actually using the few nvram bytes on a rtc chip. This patch is compile-tested only as I lack hardware with nvram. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- v2: - embed nvmem_config structure part in struct ds1307 - set name and owner members of struct nvmem_config v3: - extend Kconfig help text - use IS_REACHABLE to not access the NVMEM API if ds1307 is built-in and NVMEM is a module. I don't use Kconfig dependencies because only few supported chips have NVRAM. --- drivers/rtc/Kconfig | 5 ++- drivers/rtc/rtc-ds1307.c | 101 ++++++++++++++++++----------------------------- 2 files changed, 42 insertions(+), 64 deletions(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 8d3b9572..22ac31fd 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig@@ -219,8 +219,9 @@ config RTC_DRV_DS1307 The first seven registers on these chips hold an RTC, and other registers may add features such as NVRAM, a trickle charger for - the RTC/NVRAM backup power, and alarms. NVRAM is visible in - sysfs, but other chip features may not be available. + the RTC/NVRAM backup power, and alarms. + If your chip has NVRAM and CONFIG_NVMEM is set then the NVRAM + is accessible via sysfs. This driver can also be built as a module. If so, the module will be called rtc-ds1307.
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 79160027..a2a90cd2 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c@@ -25,6 +25,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/clk-provider.h> #include <linux/regmap.h> +#include <linux/nvmem-provider.h> /* * We can't determine type by probing, but if we expect pre-Linux code
@@ -116,11 +117,11 @@ struct ds1307 { u8 offset; /* register's offset */ u8 regs[11]; u16 nvram_offset; - struct bin_attribute *nvram; + struct nvmem_config nvram_cfg; + struct nvmem_device *nvram; enum ds_type type; unsigned long flags; -#define HAS_NVRAM 0 /* bit 0 == sysfs file active */ -#define HAS_ALARM 1 /* bit 1 == irq claimed */ +#define HAS_ALARM 0 /* bit 0 == irq claimed */ struct device *dev; struct regmap *regmap; const char *name;
@@ -676,42 +677,27 @@ 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) -{ - struct ds1307 *ds1307; - int result; +#if IS_REACHABLE(CONFIG_NVMEM) - ds1307 = dev_get_drvdata(kobj_to_dev(kobj)); +static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + 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; - - ds1307 = dev_get_drvdata(kobj_to_dev(kobj)); + struct ds1307 *ds1307 = priv; - 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); } +#endif /*----------------------------------------------------------------------*/
@@ -1475,39 +1461,28 @@ static int ds1307_probe(struct i2c_client *client, dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq); } +#if IS_REACHABLE(CONFIG_NVMEM) 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"); + ds1307->nvram_cfg.name = "ds1307_nvram"; + ds1307->nvram_cfg.dev = ds1307->dev; + ds1307->nvram_cfg.reg_read = ds1307_nvram_read; + ds1307->nvram_cfg.reg_write = ds1307_nvram_write; + ds1307->nvram_cfg.size = chip->nvram_size; + ds1307->nvram_cfg.word_size = 1; + ds1307->nvram_cfg.stride = 1; + ds1307->nvram_cfg.priv = ds1307; + ds1307->nvram_cfg.owner = THIS_MODULE; + + ds1307->nvram = nvmem_register(&ds1307->nvram_cfg); + if (IS_ERR(ds1307->nvram)) { + dev_err(ds1307->dev, "unable to register nvmem\n"); + ds1307->nvram = NULL; } 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); - } + dev_info(ds1307->dev, "%d bytes nvram\n", + chip->nvram_size); } } +#endif ds1307_hwmon_register(ds1307); ds1307_clks_register(ds1307);
@@ -1522,8 +1497,10 @@ 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); +#if IS_REACHABLE(CONFIG_NVMEM) + if (ds1307->nvram) + nvmem_unregister(ds1307->nvram); +#endif return 0; }
--
2.13.0