All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM
@ 2016-01-28 15:42 Andrew Lunn
  2016-01-28 15:42 ` [PATCH 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

This patch set converts the old EEPROM drivers in driver/misc/eeprom to
use the NVMEM framework. These drivers export there content in /sys as
read only to root, since the EEPROM may contain sensitive information.
So the first patch adds a flag so the NVMEM framework will create its
file in /sys as root read only.

To keep backwards compatibility with these older drivers, the contents
of the EEPROM must be exports in sysfs in a file called eeprom in the
devices node in sys, where as the NVMEM places them under class/nvmem.
So add this optional backwards compatible to the framework, again
using a flag.

Then convert the at24, at25 and 93xx46 by adding regmap support,
removing each drivers own /sys code and registering with the NVMEM
framework.

AT24 and 93xx46 has been boot tested, at25 compile tested only.

v2:

nvmem_register() now supports a backwards compatible flag, and the
Kconfig option has been removed.

v3:

Rebase on v4.5-rc1.
Add a patch to replace memory_accessor in the setup() callbacks with
nvmem API calls

Andrew Lunn (7):
  nvmem: Add flag to export NVMEM to root only
  nvmem: Add backwards compatibility support for older EEPROM drivers.
  eeprom: at24: extend driver to plug into the NVMEM framework
  eeprom: at25: Remove in kernel API for accessing the EEPROM
  eeprom: at25: extend driver to plug into the NVMEM framework
  eeprom: 93xx46: extend driver to plug into the NVMEM framework
  misc: at24: replace memory_accessor with nvmem_device_read

 arch/arm/mach-davinci/board-mityomapl138.c |   5 +-
 arch/arm/mach-davinci/common.c             |   4 +-
 drivers/misc/eeprom/Kconfig                |   6 ++
 drivers/misc/eeprom/at24.c                 | 130 +++++++++++++------------
 drivers/misc/eeprom/at25.c                 | 148 +++++++++++++----------------
 drivers/misc/eeprom/eeprom_93xx46.c        | 122 +++++++++++++++++++-----
 drivers/nvmem/core.c                       | 134 ++++++++++++++++++++++++--
 include/linux/davinci_emac.h               |   4 +-
 include/linux/memory.h                     |  11 ---
 include/linux/nvmem-provider.h             |   5 +-
 include/linux/platform_data/at24.h         |  10 +-
 include/linux/spi/eeprom.h                 |   2 -
 12 files changed, 380 insertions(+), 201 deletions(-)

-- 
2.7.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/7] nvmem: Add flag to export NVMEM to root only
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  2016-01-28 15:42 ` [PATCH 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers Andrew Lunn
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Legacy AT24, AT25 EEPROMs are exported in sys so that only root can
read the contents. The EEPROMs may contain sensitive information. Add
a flag so the provide can indicate that NVMEM should also restrict
access to root only.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/nvmem/core.c           | 57 ++++++++++++++++++++++++++++++++++++++++--
 include/linux/nvmem-provider.h |  1 +
 2 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6fd4e5a5ef4a..4ccf03da6467 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -155,6 +155,53 @@ static const struct attribute_group *nvmem_ro_dev_groups[] = {
 	NULL,
 };
 
+/* default read/write permissions, root only */
+static struct bin_attribute bin_attr_rw_root_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IWUSR | S_IRUSR,
+	},
+	.read	= bin_attr_nvmem_read,
+	.write	= bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
+	&bin_attr_rw_root_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_rw_root_group = {
+	.bin_attrs	= nvmem_bin_rw_root_attributes,
+};
+
+static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
+	&nvmem_bin_rw_root_group,
+	NULL,
+};
+
+/* read only permission, root only */
+static struct bin_attribute bin_attr_ro_root_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IRUSR,
+	},
+	.read	= bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
+	&bin_attr_ro_root_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_ro_root_group = {
+	.bin_attrs	= nvmem_bin_ro_root_attributes,
+};
+
+static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
+	&nvmem_bin_ro_root_group,
+	NULL,
+};
+
 static void nvmem_release(struct device *dev)
 {
 	struct nvmem_device *nvmem = to_nvmem_device(dev);
@@ -347,8 +394,14 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
 	nvmem->read_only = of_property_read_bool(np, "read-only") |
 			   config->read_only;
 
-	nvmem->dev.groups = nvmem->read_only ? nvmem_ro_dev_groups :
-					       nvmem_rw_dev_groups;
+	if (config->root_only)
+		nvmem->dev.groups = nvmem->read_only ?
+			nvmem_ro_root_dev_groups :
+			nvmem_rw_root_dev_groups;
+	else
+		nvmem->dev.groups = nvmem->read_only ?
+			nvmem_ro_dev_groups :
+			nvmem_rw_dev_groups;
 
 	device_initialize(&nvmem->dev);
 
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 0b68caff1b3c..d24fefa0c11d 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -23,6 +23,7 @@ struct nvmem_config {
 	const struct nvmem_cell_info	*cells;
 	int			ncells;
 	bool			read_only;
+	bool			root_only;
 };
 
 #if IS_ENABLED(CONFIG_NVMEM)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers.
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
  2016-01-28 15:42 ` [PATCH 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  2016-01-28 15:42 ` [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Older drivers made an 'eeprom' file available in the /sys device
directory. Have the NVMEM core provide this to retain backwards
compatibility.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/nvmem/core.c           | 77 +++++++++++++++++++++++++++++++++++++-----
 include/linux/nvmem-provider.h |  4 ++-
 2 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 4ccf03da6467..15b09ff2dac3 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -38,8 +38,13 @@ struct nvmem_device {
 	int			users;
 	size_t			size;
 	bool			read_only;
+	int			flags;
+	struct bin_attribute	eeprom;
+	struct device		*base_dev;
 };
 
+#define FLAG_COMPAT		BIT(0)
+
 struct nvmem_cell {
 	const char		*name;
 	int			offset;
@@ -62,10 +67,16 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
 				    struct bin_attribute *attr,
 				    char *buf, loff_t pos, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	struct device *dev;
+	struct nvmem_device *nvmem;
 	int rc;
 
+	if (attr->private)
+		dev = attr->private;
+	else
+		dev = container_of(kobj, struct device, kobj);
+	nvmem = to_nvmem_device(dev);
+
 	/* Stop the user from reading */
 	if (pos >= nvmem->size)
 		return 0;
@@ -87,10 +98,16 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
 				     struct bin_attribute *attr,
 				     char *buf, loff_t pos, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	struct device *dev;
+	struct nvmem_device *nvmem;
 	int rc;
 
+	if (attr->private)
+		dev = attr->private;
+	else
+		dev = container_of(kobj, struct device, kobj);
+	nvmem = to_nvmem_device(dev);
+
 	/* Stop the user from writing */
 	if (pos >= nvmem->size)
 		return 0;
@@ -341,6 +358,40 @@ err:
 	return rval;
 }
 
+/*
+ * nvmem_setup_compat() - Create an additional binary entry in
+ * drivers sys directory, to be backwards compatible with the older
+ * drivers/misc/eeprom drivers.
+ */
+static int nvmem_setup_compat(struct nvmem_device *nvmem,
+			      const struct nvmem_config *config)
+{
+	int rval;
+
+	if (!config->base_dev)
+		return -EINVAL;
+
+	if (nvmem->read_only)
+		nvmem->eeprom = bin_attr_ro_root_nvmem;
+	else
+		nvmem->eeprom = bin_attr_rw_root_nvmem;
+	nvmem->eeprom.attr.name = "eeprom";
+	nvmem->eeprom.size = nvmem->size;
+	nvmem->eeprom.private = &nvmem->dev;
+	nvmem->base_dev = config->base_dev;
+
+	rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
+	if (rval) {
+		dev_err(&nvmem->dev,
+			"Failed to create eeprom binary file %d\n", rval);
+		return rval;
+	}
+
+	nvmem->flags |= FLAG_COMPAT;
+
+	return 0;
+}
+
 /**
  * nvmem_register() - Register a nvmem device for given nvmem_config.
  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
@@ -408,16 +459,23 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
 	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
 
 	rval = device_add(&nvmem->dev);
-	if (rval) {
-		ida_simple_remove(&nvmem_ida, nvmem->id);
-		kfree(nvmem);
-		return ERR_PTR(rval);
+	if (rval)
+		goto out;
+
+	if (config->compat) {
+		rval = nvmem_setup_compat(nvmem, config);
+		if (rval)
+			goto out;
 	}
 
 	if (config->cells)
 		nvmem_add_cells(nvmem, config);
 
 	return nvmem;
+out:
+	ida_simple_remove(&nvmem_ida, nvmem->id);
+	kfree(nvmem);
+	return ERR_PTR(rval);
 }
 EXPORT_SYMBOL_GPL(nvmem_register);
 
@@ -437,6 +495,9 @@ int nvmem_unregister(struct nvmem_device *nvmem)
 	}
 	mutex_unlock(&nvmem_mutex);
 
+	if (nvmem->flags & FLAG_COMPAT)
+		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
+
 	nvmem_device_remove_all_cells(nvmem);
 	device_del(&nvmem->dev);
 
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index d24fefa0c11d..a4fcc90b0f20 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -24,6 +24,9 @@ struct nvmem_config {
 	int			ncells;
 	bool			read_only;
 	bool			root_only;
+	/* To be only used by old driver/misc/eeprom drivers */
+	bool			compat;
+	struct device		*base_dev;
 };
 
 #if IS_ENABLED(CONFIG_NVMEM)
@@ -44,5 +47,4 @@ static inline int nvmem_unregister(struct nvmem_device *nvmem)
 }
 
 #endif /* CONFIG_NVMEM */
-
 #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
  2016-01-28 15:42 ` [PATCH 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
  2016-01-28 15:42 ` [PATCH 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  2016-01-29 13:10   ` Bartosz Golaszewski
  2016-01-28 15:42 ` [PATCH 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Add a regmap for accessing the EEPROM, and then use that with the
NVMEM framework. Set the NVMEM config structure to enable backward, so
that the 'eeprom' file in sys is provided by the framework.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/misc/eeprom/Kconfig |   2 +
 drivers/misc/eeprom/at24.c  | 121 +++++++++++++++++++++++++++++---------------
 2 files changed, 82 insertions(+), 41 deletions(-)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 04f2e1fa9dd1..24935473393b 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -3,6 +3,8 @@ menu "EEPROM support"
 config EEPROM_AT24
 	tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
 	depends on I2C && SYSFS
+	select REGMAP
+	select NVMEM
 	help
 	  Enable this driver to get read/write support to most I2C EEPROMs
 	  and compatible devices like FRAMs, SRAMs, ROMs etc. After you
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 5d7c0900fa1b..f15cda93fc4c 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -15,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
-#include <linux/sysfs.h>
 #include <linux/mod_devicetable.h>
 #include <linux/log2.h>
 #include <linux/bitops.h>
@@ -23,6 +22,8 @@
 #include <linux/of.h>
 #include <linux/acpi.h>
 #include <linux/i2c.h>
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
 #include <linux/platform_data/at24.h>
 
 /*
@@ -64,12 +65,15 @@ struct at24_data {
 	 * but not from changes by other I2C masters.
 	 */
 	struct mutex lock;
-	struct bin_attribute bin;
 
 	u8 *writebuf;
 	unsigned write_max;
 	unsigned num_addresses;
 
+	struct regmap_config regmap_config;
+	struct nvmem_config nvmem_config;
+	struct nvmem_device *nvmem;
+
 	/*
 	 * Some chips tie up multiple I2C addresses; dummy devices reserve
 	 * them for us, and we'll use them with SMBus calls.
@@ -283,17 +287,6 @@ static ssize_t at24_read(struct at24_data *at24,
 	return retval;
 }
 
-static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
-{
-	struct at24_data *at24;
-
-	at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
-	return at24_read(at24, buf, off, count);
-}
-
-
 /*
  * Note that if the hardware write-protect pin is pulled high, the whole
  * chip is normally write protected. But there are plenty of product
@@ -414,16 +407,6 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
 	return retval;
 }
 
-static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
-{
-	struct at24_data *at24;
-
-	at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
-	return at24_write(at24, buf, off, count);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -450,6 +433,49 @@ static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Provide a regmap interface, which is registered with the NVMEM
+ * framework
+*/
+static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	struct at24_data *at24 = context;
+	off_t offset = *(u32 *)reg;
+	int err;
+
+	err = at24_read(at24, val, offset, val_size);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int at24_regmap_write(void *context, const void *data, size_t count)
+{
+	struct at24_data *at24 = context;
+	const char *buf;
+	u32 offset;
+	size_t len;
+	int err;
+
+	memcpy(&offset, data, sizeof(offset));
+	buf = (const char *)data + sizeof(offset);
+	len = count - sizeof(offset);
+
+	err = at24_write(at24, buf, offset, len);
+	if (err)
+		return err;
+	return 0;
+}
+
+static const struct regmap_bus at24_regmap_bus = {
+	.read = at24_regmap_read,
+	.write = at24_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+/*-------------------------------------------------------------------------*/
+
 #ifdef CONFIG_OF
 static void at24_get_ofdata(struct i2c_client *client,
 		struct at24_platform_data *chip)
@@ -481,6 +507,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	struct at24_data *at24;
 	int err;
 	unsigned i, num_addresses;
+	struct regmap *regmap;
 
 	if (client->dev.platform_data) {
 		chip = *(struct at24_platform_data *)client->dev.platform_data;
@@ -573,16 +600,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	at24->chip = chip;
 	at24->num_addresses = num_addresses;
 
-	/*
-	 * Export the EEPROM bytes through sysfs, since that's convenient.
-	 * By default, only root should see the data (maybe passwords etc)
-	 */
-	sysfs_bin_attr_init(&at24->bin);
-	at24->bin.attr.name = "eeprom";
-	at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
-	at24->bin.read = at24_bin_read;
-	at24->bin.size = chip.byte_len;
-
 	at24->macc.read = at24_macc_read;
 
 	writable = !(chip.flags & AT24_FLAG_READONLY);
@@ -593,9 +610,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 			at24->macc.write = at24_macc_write;
 
-			at24->bin.write = at24_bin_write;
-			at24->bin.attr.mode |= S_IWUSR;
-
 			if (write_max > io_limit)
 				write_max = io_limit;
 			if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
@@ -627,14 +641,38 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		}
 	}
 
-	err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
-	if (err)
+	at24->regmap_config.reg_bits = 32;
+	at24->regmap_config.val_bits = 8;
+	at24->regmap_config.reg_stride = 1;
+	at24->regmap_config.max_register = chip.byte_len - 1;
+
+	regmap = devm_regmap_init(&client->dev, &at24_regmap_bus, at24,
+				  &at24->regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "regmap init failed\n");
+		err = PTR_ERR(regmap);
 		goto err_clients;
+	}
+
+	at24->nvmem_config.name = dev_name(&client->dev);
+	at24->nvmem_config.dev = &client->dev;
+	at24->nvmem_config.read_only = !writable;
+	at24->nvmem_config.root_only = true;
+	at24->nvmem_config.owner = THIS_MODULE;
+	at24->nvmem_config.compat = true;
+	at24->nvmem_config.base_dev = &client->dev;
+
+	at24->nvmem = nvmem_register(&at24->nvmem_config);
+
+	if (IS_ERR(at24->nvmem)) {
+		err = PTR_ERR(at24->nvmem);
+		goto err_clients;
+	}
 
 	i2c_set_clientdata(client, at24);
 
-	dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n",
-		at24->bin.size, client->name,
+	dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
+		chip.byte_len, client->name,
 		writable ? "writable" : "read-only", at24->write_max);
 	if (use_smbus == I2C_SMBUS_WORD_DATA ||
 	    use_smbus == I2C_SMBUS_BYTE_DATA) {
@@ -663,7 +701,8 @@ static int at24_remove(struct i2c_client *client)
 	int i;
 
 	at24 = i2c_get_clientdata(client);
-	sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
+
+	nvmem_unregister(at24->nvmem);
 
 	for (i = 1; i < at24->num_addresses; i++)
 		i2c_unregister_device(at24->client[i]);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (2 preceding siblings ...)
  2016-01-28 15:42 ` [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  2016-01-28 15:42 ` [PATCH 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

The setup() callback is not used by any in kernel code. Remove it.
Any new code which requires access to the eeprom can use the NVMEM
API.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/misc/eeprom/at25.c | 26 --------------------------
 include/linux/spi/eeprom.h |  2 --
 2 files changed, 28 deletions(-)

diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index f850ef556bcc..4732f6997289 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -29,7 +29,6 @@
 
 struct at25_data {
 	struct spi_device	*spi;
-	struct memory_accessor	mem;
 	struct mutex		lock;
 	struct spi_eeprom	chip;
 	struct bin_attribute	bin;
@@ -281,26 +280,6 @@ at25_bin_write(struct file *filp, struct kobject *kobj,
 
 /*-------------------------------------------------------------------------*/
 
-/* Let in-kernel code access the eeprom data. */
-
-static ssize_t at25_mem_read(struct memory_accessor *mem, char *buf,
-			 off_t offset, size_t count)
-{
-	struct at25_data *at25 = container_of(mem, struct at25_data, mem);
-
-	return at25_ee_read(at25, buf, offset, count);
-}
-
-static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
-			  off_t offset, size_t count)
-{
-	struct at25_data *at25 = container_of(mem, struct at25_data, mem);
-
-	return at25_ee_write(at25, buf, offset, count);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
 {
 	u32 val;
@@ -415,22 +394,17 @@ static int at25_probe(struct spi_device *spi)
 	at25->bin.attr.name = "eeprom";
 	at25->bin.attr.mode = S_IRUSR;
 	at25->bin.read = at25_bin_read;
-	at25->mem.read = at25_mem_read;
 
 	at25->bin.size = at25->chip.byte_len;
 	if (!(chip.flags & EE_READONLY)) {
 		at25->bin.write = at25_bin_write;
 		at25->bin.attr.mode |= S_IWUSR;
-		at25->mem.write = at25_mem_write;
 	}
 
 	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
 	if (err)
 		return err;
 
-	if (chip.setup)
-		chip.setup(&at25->mem, chip.context);
-
 	dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
 		(at25->bin.size < 1024)
 			? at25->bin.size
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
index 403e007aef68..e34e169f9dcb 100644
--- a/include/linux/spi/eeprom.h
+++ b/include/linux/spi/eeprom.h
@@ -30,8 +30,6 @@ struct spi_eeprom {
 	 */
 #define EE_INSTR_BIT3_IS_ADDR	0x0010
 
-	/* for exporting this chip's data to other kernel code */
-	void (*setup)(struct memory_accessor *mem, void *context);
 	void *context;
 };
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/7] eeprom: at25: extend driver to plug into the NVMEM framework
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (3 preceding siblings ...)
  2016-01-28 15:42 ` [PATCH 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  2016-01-28 15:42 ` [PATCH 6/7] eeprom: 93xx46: " Andrew Lunn
  2016-01-28 15:42 ` [PATCH 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Add a regmap for accessing the EEPROM, and then use that with the
NVMEM framework. Enable backwards compatibility in the NVMEM config,
so that the 'eeprom' file in sys is provided by the framework.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/misc/eeprom/Kconfig |   2 +
 drivers/misc/eeprom/at25.c  | 124 ++++++++++++++++++++++++--------------------
 2 files changed, 71 insertions(+), 55 deletions(-)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 24935473393b..8c43a222ae55 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -32,6 +32,8 @@ config EEPROM_AT24
 config EEPROM_AT25
 	tristate "SPI EEPROMs from most vendors"
 	depends on SPI && SYSFS
+	select REGMAP
+	select NVMEM
 	help
 	  Enable this driver to get read/write support to most SPI EEPROMs,
 	  after you configure the board init code to know about each eeprom
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 4732f6997289..fa36a6e37084 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -16,6 +16,8 @@
 #include <linux/device.h>
 #include <linux/sched.h>
 
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
 #include <linux/property.h>
@@ -31,8 +33,10 @@ struct at25_data {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct spi_eeprom	chip;
-	struct bin_attribute	bin;
 	unsigned		addrlen;
+	struct regmap_config	regmap_config;
+	struct nvmem_config	nvmem_config;
+	struct nvmem_device	*nvmem;
 };
 
 #define	AT25_WREN	0x06		/* latch the write enable */
@@ -76,10 +80,10 @@ at25_ee_read(
 	struct spi_message	m;
 	u8			instr;
 
-	if (unlikely(offset >= at25->bin.size))
+	if (unlikely(offset >= at25->chip.byte_len))
 		return 0;
-	if ((offset + count) > at25->bin.size)
-		count = at25->bin.size - offset;
+	if ((offset + count) > at25->chip.byte_len)
+		count = at25->chip.byte_len - offset;
 	if (unlikely(!count))
 		return count;
 
@@ -130,21 +134,19 @@ at25_ee_read(
 	return status ? status : count;
 }
 
-static ssize_t
-at25_bin_read(struct file *filp, struct kobject *kobj,
-	      struct bin_attribute *bin_attr,
-	      char *buf, loff_t off, size_t count)
+static int at25_regmap_read(void *context, const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
 {
-	struct device		*dev;
-	struct at25_data	*at25;
-
-	dev = container_of(kobj, struct device, kobj);
-	at25 = dev_get_drvdata(dev);
+	struct at25_data *at25 = context;
+	off_t offset = *(u32 *)reg;
+	int err;
 
-	return at25_ee_read(at25, buf, off, count);
+	err = at25_ee_read(at25, val, offset, val_size);
+	if (err)
+		return err;
+	return 0;
 }
 
-
 static ssize_t
 at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
 	      size_t count)
@@ -154,10 +156,10 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
 	unsigned		buf_size;
 	u8			*bounce;
 
-	if (unlikely(off >= at25->bin.size))
+	if (unlikely(off >= at25->chip.byte_len))
 		return -EFBIG;
-	if ((off + count) > at25->bin.size)
-		count = at25->bin.size - off;
+	if ((off + count) > at25->chip.byte_len)
+		count = at25->chip.byte_len - off;
 	if (unlikely(!count))
 		return count;
 
@@ -264,20 +266,30 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
 	return written ? written : status;
 }
 
-static ssize_t
-at25_bin_write(struct file *filp, struct kobject *kobj,
-	       struct bin_attribute *bin_attr,
-	       char *buf, loff_t off, size_t count)
+static int at25_regmap_write(void *context, const void *data, size_t count)
 {
-	struct device		*dev;
-	struct at25_data	*at25;
+	struct at25_data *at25 = context;
+	const char *buf;
+	u32 offset;
+	size_t len;
+	int err;
 
-	dev = container_of(kobj, struct device, kobj);
-	at25 = dev_get_drvdata(dev);
+	memcpy(&offset, data, sizeof(offset));
+	buf = (const char *)data + sizeof(offset);
+	len = count - sizeof(offset);
 
-	return at25_ee_write(at25, buf, off, count);
+	err = at25_ee_write(at25, buf, offset, len);
+	if (err)
+		return err;
+	return 0;
 }
 
+static const struct regmap_bus at25_regmap_bus = {
+	.read = at25_regmap_read,
+	.write = at25_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
 /*-------------------------------------------------------------------------*/
 
 static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
@@ -337,6 +349,7 @@ static int at25_probe(struct spi_device *spi)
 {
 	struct at25_data	*at25 = NULL;
 	struct spi_eeprom	chip;
+	struct regmap		*regmap;
 	int			err;
 	int			sr;
 	int			addrlen;
@@ -381,35 +394,35 @@ static int at25_probe(struct spi_device *spi)
 	spi_set_drvdata(spi, at25);
 	at25->addrlen = addrlen;
 
-	/* Export the EEPROM bytes through sysfs, since that's convenient.
-	 * And maybe to other kernel code; it might hold a board's Ethernet
-	 * address, or board-specific calibration data generated on the
-	 * manufacturing floor.
-	 *
-	 * Default to root-only access to the data; EEPROMs often hold data
-	 * that's sensitive for read and/or write, like ethernet addresses,
-	 * security codes, board-specific manufacturing calibrations, etc.
-	 */
-	sysfs_bin_attr_init(&at25->bin);
-	at25->bin.attr.name = "eeprom";
-	at25->bin.attr.mode = S_IRUSR;
-	at25->bin.read = at25_bin_read;
-
-	at25->bin.size = at25->chip.byte_len;
-	if (!(chip.flags & EE_READONLY)) {
-		at25->bin.write = at25_bin_write;
-		at25->bin.attr.mode |= S_IWUSR;
-	}
+	at25->regmap_config.reg_bits = 32;
+	at25->regmap_config.val_bits = 8;
+	at25->regmap_config.reg_stride = 1;
+	at25->regmap_config.max_register = chip.byte_len - 1;
 
-	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
-	if (err)
-		return err;
+	regmap = devm_regmap_init(&spi->dev, &at25_regmap_bus, at25,
+				  &at25->regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
 
-	dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
-		(at25->bin.size < 1024)
-			? at25->bin.size
-			: (at25->bin.size / 1024),
-		(at25->bin.size < 1024) ? "Byte" : "KByte",
+	at25->nvmem_config.name = dev_name(&spi->dev);
+	at25->nvmem_config.dev = &spi->dev;
+	at25->nvmem_config.read_only = chip.flags & EE_READONLY;
+	at25->nvmem_config.root_only = true;
+	at25->nvmem_config.owner = THIS_MODULE;
+	at25->nvmem_config.compat = true;
+	at25->nvmem_config.base_dev = &spi->dev;
+
+	at25->nvmem = nvmem_register(&at25->nvmem_config);
+	if (IS_ERR(at25->nvmem))
+		return PTR_ERR(at25->nvmem);
+
+	dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n",
+		(chip.byte_len < 1024)
+			? chip.byte_len
+			: (chip.byte_len / 1024),
+		(chip.byte_len < 1024) ? "Byte" : "KByte",
 		at25->chip.name,
 		(chip.flags & EE_READONLY) ? " (readonly)" : "",
 		at25->chip.page_size);
@@ -421,7 +434,8 @@ static int at25_remove(struct spi_device *spi)
 	struct at25_data	*at25;
 
 	at25 = spi_get_drvdata(spi);
-	sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin);
+	nvmem_unregister(at25->nvmem);
+
 	return 0;
 }
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/7] eeprom: 93xx46: extend driver to plug into the NVMEM framework
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (4 preceding siblings ...)
  2016-01-28 15:42 ` [PATCH 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  2016-01-28 15:42 ` [PATCH 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Add a regmap for accessing the EEPROM, and then use that with the
NVMEM framework. Enable backward compatibility in the MVMEM config
structure, so that the 'eeprom' file in sys is provided by the
framework.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/misc/eeprom/Kconfig         |   2 +
 drivers/misc/eeprom/eeprom_93xx46.c | 122 ++++++++++++++++++++++++++++--------
 2 files changed, 98 insertions(+), 26 deletions(-)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 8c43a222ae55..cfc493c2e30a 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -78,6 +78,8 @@ config EEPROM_93CX6
 config EEPROM_93XX46
 	tristate "Microwire EEPROM 93XX46 support"
 	depends on SPI && SYSFS
+	select REGMAP
+	select NVMEM
 	help
 	  Driver for the microwire EEPROM chipsets 93xx46x. The driver
 	  supports both read and write commands and also the command to
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index ff63f05edc76..feb74d3f95b5 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -15,7 +15,8 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/sysfs.h>
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
 #include <linux/eeprom_93xx46.h>
 
 #define OP_START	0x4
@@ -28,25 +29,29 @@
 struct eeprom_93xx46_dev {
 	struct spi_device *spi;
 	struct eeprom_93xx46_platform_data *pdata;
-	struct bin_attribute bin;
 	struct mutex lock;
+	struct regmap_config regmap_config;
+	struct nvmem_config nvmem_config;
+	struct nvmem_device *nvmem;
 	int addrlen;
+	int size;
 };
 
 static ssize_t
-eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
-		       struct bin_attribute *bin_attr,
-		       char *buf, loff_t off, size_t count)
+eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
+		   unsigned off, size_t count)
 {
-	struct eeprom_93xx46_dev *edev;
-	struct device *dev;
 	struct spi_message m;
 	struct spi_transfer t[2];
 	int bits, ret;
 	u16 cmd_addr;
 
-	dev = container_of(kobj, struct device, kobj);
-	edev = dev_get_drvdata(dev);
+	if (unlikely(off >= edev->size))
+		return 0;
+	if ((off + count) > edev->size)
+		count = edev->size - off;
+	if (unlikely(!count))
+		return count;
 
 	cmd_addr = OP_READ << edev->addrlen;
 
@@ -94,6 +99,7 @@ eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
 	return ret ? : count;
 }
 
+
 static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
 {
 	struct spi_message m;
@@ -182,16 +188,17 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
 }
 
 static ssize_t
-eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
-			struct bin_attribute *bin_attr,
-			char *buf, loff_t off, size_t count)
+eeprom_93xx46_write(struct eeprom_93xx46_dev *edev, const char *buf,
+		    loff_t off, size_t count)
 {
-	struct eeprom_93xx46_dev *edev;
-	struct device *dev;
 	int i, ret, step = 1;
 
-	dev = container_of(kobj, struct device, kobj);
-	edev = dev_get_drvdata(dev);
+	if (unlikely(off >= edev->size))
+		return -EFBIG;
+	if ((off + count) > edev->size)
+		count = edev->size - off;
+	if (unlikely(!count))
+		return count;
 
 	/* only write even number of bytes on 16-bit devices */
 	if (edev->addrlen == 6) {
@@ -228,6 +235,49 @@ eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
 	return ret ? : count;
 }
 
+/*
+ * Provide a regmap interface, which is registered with the NVMEM
+ * framework
+*/
+static int eeprom_93xx46_regmap_read(void *context, const void *reg,
+				     size_t reg_size, void *val,
+				     size_t val_size)
+{
+	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
+	off_t offset = *(u32 *)reg;
+	int err;
+
+	err = eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int eeprom_93xx46_regmap_write(void *context, const void *data,
+				      size_t count)
+{
+	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
+	const char *buf;
+	u32 offset;
+	size_t len;
+	int err;
+
+	memcpy(&offset, data, sizeof(offset));
+	buf = (const char *)data + sizeof(offset);
+	len = count - sizeof(offset);
+
+	err = eeprom_93xx46_write(eeprom_93xx46, buf, offset, len);
+	if (err)
+		return err;
+	return 0;
+}
+
+static const struct regmap_bus eeprom_93xx46_regmap_bus = {
+	.read = eeprom_93xx46_regmap_read,
+	.write = eeprom_93xx46_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
 static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
 {
 	struct eeprom_93xx46_platform_data *pd = edev->pdata;
@@ -298,6 +348,7 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
 {
 	struct eeprom_93xx46_platform_data *pd;
 	struct eeprom_93xx46_dev *edev;
+	struct regmap *regmap;
 	int err;
 
 	pd = spi->dev.platform_data;
@@ -325,19 +376,37 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
 	edev->spi = spi_dev_get(spi);
 	edev->pdata = pd;
 
-	sysfs_bin_attr_init(&edev->bin);
-	edev->bin.attr.name = "eeprom";
-	edev->bin.attr.mode = S_IRUSR;
-	edev->bin.read = eeprom_93xx46_bin_read;
-	edev->bin.size = 128;
+	edev->size = 128;
+
 	if (!(pd->flags & EE_READONLY)) {
-		edev->bin.write = eeprom_93xx46_bin_write;
-		edev->bin.attr.mode |= S_IWUSR;
 	}
 
-	err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin);
-	if (err)
+	edev->regmap_config.reg_bits = 32;
+	edev->regmap_config.val_bits = 8;
+	edev->regmap_config.reg_stride = 1;
+	edev->regmap_config.max_register = edev->size - 1;
+
+	regmap = devm_regmap_init(&spi->dev, &eeprom_93xx46_regmap_bus, edev,
+				  &edev->regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "regmap init failed\n");
+		err = PTR_ERR(regmap);
 		goto fail;
+	}
+
+	edev->nvmem_config.name = dev_name(&spi->dev);
+	edev->nvmem_config.dev = &spi->dev;
+	edev->nvmem_config.read_only = pd->flags & EE_READONLY;
+	edev->nvmem_config.root_only = true;
+	edev->nvmem_config.owner = THIS_MODULE;
+	edev->nvmem_config.compat = true;
+	edev->nvmem_config.base_dev = &spi->dev;
+
+	edev->nvmem = nvmem_register(&edev->nvmem_config);
+	if (IS_ERR(edev->nvmem)) {
+		err = PTR_ERR(edev->nvmem);
+		goto fail;
+	}
 
 	dev_info(&spi->dev, "%d-bit eeprom %s\n",
 		(pd->flags & EE_ADDR8) ? 8 : 16,
@@ -359,10 +428,11 @@ static int eeprom_93xx46_remove(struct spi_device *spi)
 {
 	struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi);
 
+	nvmem_unregister(edev->nvmem);
+
 	if (!(edev->pdata->flags & EE_READONLY))
 		device_remove_file(&spi->dev, &dev_attr_erase);
 
-	sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin);
 	kfree(edev);
 	return 0;
 }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/7] misc: at24: replace memory_accessor with nvmem_device_read
  2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (5 preceding siblings ...)
  2016-01-28 15:42 ` [PATCH 6/7] eeprom: 93xx46: " Andrew Lunn
@ 2016-01-28 15:42 ` Andrew Lunn
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-01-28 15:42 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz, fd,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Now that the AT24 uses the NVMEM framework, replace the
memory_accessor in the setup() callback with nvmem API calls.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 arch/arm/mach-davinci/board-mityomapl138.c |  5 +++--
 arch/arm/mach-davinci/common.c             |  4 ++--
 drivers/misc/eeprom/at24.c                 | 31 +-----------------------------
 include/linux/davinci_emac.h               |  4 ++--
 include/linux/memory.h                     | 11 -----------
 include/linux/platform_data/at24.h         | 10 +++++-----
 6 files changed, 13 insertions(+), 52 deletions(-)

diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index de1316bf643a..62ebac51bab9 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -115,13 +115,14 @@ static void mityomapl138_cpufreq_init(const char *partnum)
 static void mityomapl138_cpufreq_init(const char *partnum) { }
 #endif
 
-static void read_factory_config(struct memory_accessor *a, void *context)
+static void read_factory_config(struct nvmem_device *nvmem, void *context)
 {
 	int ret;
 	const char *partnum = NULL;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
-	ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
+	ret = nvmem_device_read(nvmem, 0, sizeof(factory_config),
+				&factory_config);
 	if (ret != sizeof(struct factory_config)) {
 		pr_warn("Read Factory Config Failed: %d\n", ret);
 		goto bad_config;
diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c
index a794f6d9d444..f55ef2ef2f92 100644
--- a/arch/arm/mach-davinci/common.c
+++ b/arch/arm/mach-davinci/common.c
@@ -28,13 +28,13 @@ EXPORT_SYMBOL(davinci_soc_info);
 void __iomem *davinci_intc_base;
 int davinci_intc_type;
 
-void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context)
+void davinci_get_mac_addr(struct nvmem_device *nvmem, void *context)
 {
 	char *mac_addr = davinci_soc_info.emac_pdata->mac_addr;
 	off_t offset = (off_t)context;
 
 	/* Read MAC addr from EEPROM */
-	if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+	if (nvmem_device_read(nvmem, offset, ETH_ALEN, mac_addr) == ETH_ALEN)
 		pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
 }
 
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f15cda93fc4c..089d6943f68a 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -56,7 +56,6 @@
 
 struct at24_data {
 	struct at24_platform_data chip;
-	struct memory_accessor macc;
 	int use_smbus;
 	int use_smbus_write;
 
@@ -410,30 +409,6 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
 /*-------------------------------------------------------------------------*/
 
 /*
- * This lets other kernel code access the eeprom data. For example, it
- * might hold a board's Ethernet address, or board-specific calibration
- * data generated on the manufacturing floor.
- */
-
-static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf,
-			 off_t offset, size_t count)
-{
-	struct at24_data *at24 = container_of(macc, struct at24_data, macc);
-
-	return at24_read(at24, buf, offset, count);
-}
-
-static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
-			  off_t offset, size_t count)
-{
-	struct at24_data *at24 = container_of(macc, struct at24_data, macc);
-
-	return at24_write(at24, buf, offset, count);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
  * Provide a regmap interface, which is registered with the NVMEM
  * framework
 */
@@ -600,16 +575,12 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	at24->chip = chip;
 	at24->num_addresses = num_addresses;
 
-	at24->macc.read = at24_macc_read;
-
 	writable = !(chip.flags & AT24_FLAG_READONLY);
 	if (writable) {
 		if (!use_smbus || use_smbus_write) {
 
 			unsigned write_max = chip.page_size;
 
-			at24->macc.write = at24_macc_write;
-
 			if (write_max > io_limit)
 				write_max = io_limit;
 			if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
@@ -683,7 +654,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	/* export data to kernel code */
 	if (chip.setup)
-		chip.setup(&at24->macc, chip.context);
+		chip.setup(at24->nvmem, chip.context);
 
 	return 0;
 
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 542888504994..05b97144d342 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -12,7 +12,7 @@
 #define _LINUX_DAVINCI_EMAC_H
 
 #include <linux/if_ether.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
 
 struct mdio_platform_data {
 	unsigned long		bus_freq;
@@ -46,5 +46,5 @@ enum {
 	EMAC_VERSION_2,	/* DM646x */
 };
 
-void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context);
+void davinci_get_mac_addr(struct nvmem_device *nvmem, void *context);
 #endif
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 8b8d8d12348e..b723a686fc10 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -137,17 +137,6 @@ extern struct memory_block *find_memory_block(struct mem_section *);
 #endif
 
 /*
- * 'struct memory_accessor' is a generic interface to provide
- * in-kernel access to persistent memory such as i2c or SPI EEPROMs
- */
-struct memory_accessor {
-	ssize_t (*read)(struct memory_accessor *, char *buf, off_t offset,
-			size_t count);
-	ssize_t (*write)(struct memory_accessor *, const char *buf,
-			 off_t offset, size_t count);
-};
-
-/*
  * Kernel text modification mutex, used for code patching. Users of this lock
  * can sleep.
  */
diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h
index c42aa89d34ee..dc9a13e5acda 100644
--- a/include/linux/platform_data/at24.h
+++ b/include/linux/platform_data/at24.h
@@ -9,7 +9,7 @@
 #define _LINUX_AT24_H
 
 #include <linux/types.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
 
 /**
  * struct at24_platform_data - data to set up at24 (generic eeprom) driver
@@ -17,7 +17,7 @@
  * @page_size: number of byte which can be written in one go
  * @flags: tunable options, check AT24_FLAG_* defines
  * @setup: an optional callback invoked after eeprom is probed; enables kernel
-	code to access eeprom via memory_accessor, see example
+	code to access eeprom via nvmem, see example
  * @context: optional parameter passed to setup()
  *
  * If you set up a custom eeprom type, please double-check the parameters.
@@ -26,13 +26,13 @@
  *
  * An example in pseudo code for a setup() callback:
  *
- * void get_mac_addr(struct memory_accessor *mem_acc, void *context)
+ * void get_mac_addr(struct mvmem_device *nvmem, void *context)
  * {
  *	u8 *mac_addr = ethernet_pdata->mac_addr;
  *	off_t offset = context;
  *
  *	// Read MAC addr from EEPROM
- *	if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+ *	if (nvmem_device_read(nvmem, offset, ETH_ALEN, mac_addr) == ETH_ALEN)
  *		pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
  * }
  *
@@ -48,7 +48,7 @@ struct at24_platform_data {
 #define AT24_FLAG_IRUGO		0x20	/* sysfs-entry will be world-readable */
 #define AT24_FLAG_TAKE8ADDR	0x10	/* take always 8 addresses (24c00) */
 
-	void		(*setup)(struct memory_accessor *, void *context);
+	void		(*setup)(struct nvmem_device *nvmem, void *context);
 	void		*context;
 };
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-01-28 15:42 ` [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-01-29 13:10   ` Bartosz Golaszewski
  2016-02-02  2:28     ` Andrew Lunn
  2016-02-12  9:16     ` Andrew Lunn
  0 siblings, 2 replies; 12+ messages in thread
From: Bartosz Golaszewski @ 2016-01-29 13:10 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, Srinivas Kandagatla, Maxime Ripard, Wolfram Sang,
	broonie, vz, fd, LKML, Pantelis Antoniou

2016-01-28 16:42 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
> Add a regmap for accessing the EEPROM, and then use that with the
> NVMEM framework. Set the NVMEM config structure to enable backward, so
> that the 'eeprom' file in sys is provided by the framework.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/misc/eeprom/Kconfig |   2 +
>  drivers/misc/eeprom/at24.c  | 121 +++++++++++++++++++++++++++++---------------
>  2 files changed, 82 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
> index 04f2e1fa9dd1..24935473393b 100644
> --- a/drivers/misc/eeprom/Kconfig
> +++ b/drivers/misc/eeprom/Kconfig
> @@ -3,6 +3,8 @@ menu "EEPROM support"
>  config EEPROM_AT24
>         tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
>         depends on I2C && SYSFS
> +       select REGMAP
> +       select NVMEM
>         help
>           Enable this driver to get read/write support to most I2C EEPROMs
>           and compatible devices like FRAMs, SRAMs, ROMs etc. After you
> diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
> index 5d7c0900fa1b..f15cda93fc4c 100644
> --- a/drivers/misc/eeprom/at24.c
> +++ b/drivers/misc/eeprom/at24.c
> @@ -15,7 +15,6 @@
>  #include <linux/slab.h>
>  #include <linux/delay.h>
>  #include <linux/mutex.h>
> -#include <linux/sysfs.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/log2.h>
>  #include <linux/bitops.h>
> @@ -23,6 +22,8 @@
>  #include <linux/of.h>
>  #include <linux/acpi.h>
>  #include <linux/i2c.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/regmap.h>
>  #include <linux/platform_data/at24.h>
>
>  /*
> @@ -64,12 +65,15 @@ struct at24_data {
>          * but not from changes by other I2C masters.
>          */
>         struct mutex lock;
> -       struct bin_attribute bin;
>
>         u8 *writebuf;
>         unsigned write_max;
>         unsigned num_addresses;
>
> +       struct regmap_config regmap_config;
> +       struct nvmem_config nvmem_config;
> +       struct nvmem_device *nvmem;
> +
>         /*
>          * Some chips tie up multiple I2C addresses; dummy devices reserve
>          * them for us, and we'll use them with SMBus calls.
> @@ -283,17 +287,6 @@ static ssize_t at24_read(struct at24_data *at24,
>         return retval;
>  }
>
> -static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj,
> -               struct bin_attribute *attr,
> -               char *buf, loff_t off, size_t count)
> -{
> -       struct at24_data *at24;
> -
> -       at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
> -       return at24_read(at24, buf, off, count);
> -}
> -
> -
>  /*
>   * Note that if the hardware write-protect pin is pulled high, the whole
>   * chip is normally write protected. But there are plenty of product
> @@ -414,16 +407,6 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
>         return retval;
>  }
>
> -static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
> -               struct bin_attribute *attr,
> -               char *buf, loff_t off, size_t count)
> -{
> -       struct at24_data *at24;
> -
> -       at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
> -       return at24_write(at24, buf, off, count);
> -}
> -
>  /*-------------------------------------------------------------------------*/
>
>  /*
> @@ -450,6 +433,49 @@ static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
>
>  /*-------------------------------------------------------------------------*/
>
> +/*
> + * Provide a regmap interface, which is registered with the NVMEM
> + * framework
> +*/
> +static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
> +                           void *val, size_t val_size)
> +{
> +       struct at24_data *at24 = context;
> +       off_t offset = *(u32 *)reg;
> +       int err;
> +
> +       err = at24_read(at24, val, offset, val_size);
> +       if (err)
> +               return err;
> +       return 0;
> +}
> +
> +static int at24_regmap_write(void *context, const void *data, size_t count)
> +{
> +       struct at24_data *at24 = context;
> +       const char *buf;
> +       u32 offset;
> +       size_t len;
> +       int err;
> +
> +       memcpy(&offset, data, sizeof(offset));
> +       buf = (const char *)data + sizeof(offset);
> +       len = count - sizeof(offset);
> +
> +       err = at24_write(at24, buf, offset, len);
> +       if (err)
> +               return err;
> +       return 0;
> +}
> +
> +static const struct regmap_bus at24_regmap_bus = {
> +       .read = at24_regmap_read,
> +       .write = at24_regmap_write,
> +       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
> +};
> +
> +/*-------------------------------------------------------------------------*/
> +
>  #ifdef CONFIG_OF
>  static void at24_get_ofdata(struct i2c_client *client,
>                 struct at24_platform_data *chip)
> @@ -481,6 +507,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>         struct at24_data *at24;
>         int err;
>         unsigned i, num_addresses;
> +       struct regmap *regmap;
>
>         if (client->dev.platform_data) {
>                 chip = *(struct at24_platform_data *)client->dev.platform_data;
> @@ -573,16 +600,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>         at24->chip = chip;
>         at24->num_addresses = num_addresses;
>
> -       /*
> -        * Export the EEPROM bytes through sysfs, since that's convenient.
> -        * By default, only root should see the data (maybe passwords etc)
> -        */
> -       sysfs_bin_attr_init(&at24->bin);
> -       at24->bin.attr.name = "eeprom";
> -       at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
> -       at24->bin.read = at24_bin_read;
> -       at24->bin.size = chip.byte_len;
> -
>         at24->macc.read = at24_macc_read;
>
>         writable = !(chip.flags & AT24_FLAG_READONLY);
> @@ -593,9 +610,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>
>                         at24->macc.write = at24_macc_write;
>
> -                       at24->bin.write = at24_bin_write;
> -                       at24->bin.attr.mode |= S_IWUSR;
> -
>                         if (write_max > io_limit)
>                                 write_max = io_limit;
>                         if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
> @@ -627,14 +641,38 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>                 }
>         }
>
> -       err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
> -       if (err)
> +       at24->regmap_config.reg_bits = 32;
> +       at24->regmap_config.val_bits = 8;
> +       at24->regmap_config.reg_stride = 1;
> +       at24->regmap_config.max_register = chip.byte_len - 1;
> +
> +       regmap = devm_regmap_init(&client->dev, &at24_regmap_bus, at24,
> +                                 &at24->regmap_config);
> +       if (IS_ERR(regmap)) {
> +               dev_err(&client->dev, "regmap init failed\n");
> +               err = PTR_ERR(regmap);
>                 goto err_clients;
> +       }
> +
> +       at24->nvmem_config.name = dev_name(&client->dev);
> +       at24->nvmem_config.dev = &client->dev;
> +       at24->nvmem_config.read_only = !writable;
> +       at24->nvmem_config.root_only = true;
> +       at24->nvmem_config.owner = THIS_MODULE;
> +       at24->nvmem_config.compat = true;
> +       at24->nvmem_config.base_dev = &client->dev;
> +
> +       at24->nvmem = nvmem_register(&at24->nvmem_config);
> +
> +       if (IS_ERR(at24->nvmem)) {
> +               err = PTR_ERR(at24->nvmem);
> +               goto err_clients;
> +       }
>
>         i2c_set_clientdata(client, at24);
>
> -       dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n",
> -               at24->bin.size, client->name,
> +       dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
> +               chip.byte_len, client->name,
>                 writable ? "writable" : "read-only", at24->write_max);
>         if (use_smbus == I2C_SMBUS_WORD_DATA ||
>             use_smbus == I2C_SMBUS_BYTE_DATA) {
> @@ -663,7 +701,8 @@ static int at24_remove(struct i2c_client *client)
>         int i;
>
>         at24 = i2c_get_clientdata(client);
> -       sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
> +
> +       nvmem_unregister(at24->nvmem);
>
>         for (i = 1; i < at24->num_addresses; i++)
>                 i2c_unregister_device(at24->client[i]);
> --
> 2.7.0
>

Hi Andrew,

the patch works, but I'm hitting the following BUG when instantiating
an at24c32 device:

# echo 24c32 0x54 > /sys/class/i2c-adapter/i2c-2/new_device
[    3.741893] BUG: key de753e8c not in .data!
[    3.749166] ------------[ cut here ]------------
[    3.756649] WARNING: CPU: 0 PID: 102 at
kernel/locking/lockdep.c:3002 __kernfs_create_file+0x60/0xc4()
[    3.769048] DEBUG_LOCKS_WARN_ON(1)
[    3.772463] Modules linked in: at24(+) nvmem_core cpufreq_dt
omap_wdt thermal_sys leds_gpio led_class hwmon
[    3.788301] CPU: 0 PID: 102 Comm: udevd Not tainted 4.5.0-rc1-acme+ #7
[    3.797833] Hardware name: Generic AM33XX (Flattened Device Tree)
[    3.806920] [<c0017d44>] (unwind_backtrace) from [<c0014034>]
(show_stack+0x10/0x14)
[    3.817762] [<c0014034>] (show_stack) from [<c036b478>]
(dump_stack+0x84/0x9c)
[    3.828071] [<c036b478>] (dump_stack) from [<c003c850>]
(warn_slowpath_common+0x7c/0xb8)
[    3.839284] [<c003c850>] (warn_slowpath_common) from [<c003c8bc>]
(warn_slowpath_fmt+0x30/0x40)
[    3.851154] [<c003c8bc>] (warn_slowpath_fmt) from [<c01fbf3c>]
(__kernfs_create_file+0x60/0xc4)
[    3.863025] [<c01fbf3c>] (__kernfs_create_file) from [<c01fc794>]
(sysfs_add_file_mode_ns+0x98/0x1bc)
[    3.875488] [<c01fc794>] (sysfs_add_file_mode_ns) from [<c01fca40>]
(sysfs_create_bin_file+0x38/0x44)
[    3.888000] [<c01fca40>] (sysfs_create_bin_file) from [<bf033770>]
(nvmem_register+0x2cc/0x34c [nvmem_core])
[    3.901190] [<bf033770>] (nvmem_register [nvmem_core]) from
[<bf03c958>] (at24_probe+0x430/0x59c [at24])
[    3.914055] [<bf03c958>] (at24_probe [at24]) from [<c054be80>]
(i2c_device_probe+0x168/0x1fc)
[    3.925926] [<c054be80>] (i2c_device_probe) from [<c045ba44>]
(driver_probe_device+0x208/0x2c0)
[    3.938003] [<c045ba44>] (driver_probe_device) from [<c045bb90>]
(__driver_attach+0x94/0x98)
[    3.949821] [<c045bb90>] (__driver_attach) from [<c0459d80>]
(bus_for_each_dev+0x6c/0xa0)
[    3.961373] [<c0459d80>] (bus_for_each_dev) from [<c045b038>]
(bus_add_driver+0x18c/0x214)
[    3.973037] [<c045b038>] (bus_add_driver) from [<c045c4f4>]
(driver_register+0x78/0xf8)
[    3.984458] [<c045c4f4>] (driver_register) from [<c054ca00>]
(i2c_register_driver+0x2c/0x80)
[    3.996349] [<c054ca00>] (i2c_register_driver) from [<c0009804>]
(do_one_initcall+0x80/0x1e0)
[    4.008344] [<c0009804>] (do_one_initcall) from [<c0123110>]
(do_init_module+0x5c/0x1d4)
[    4.019910] [<c0123110>] (do_init_module) from [<c00cb2e4>]
(load_module+0x1cc0/0x1f48)
[    4.031378] [<c00cb2e4>] (load_module) from [<c00cb71c>]
(SyS_finit_module+0x64/0x74)
[    4.042665] [<c00cb71c>] (SyS_finit_module) from [<c000f820>]
(ret_fast_syscall+0x0/0x1c)
[    4.054322] ---[ end trace 692db3ff57b96549 ]---
[    4.062228] at24 2-0054: 4096 byte 24c32 EEPROM, writable, 1 bytes/write
[    4.073224] i2c i2c-2: new_device: Instantiated device 24c32 at 0x54

It seems to result in the nvmem attribute having 0 size while the
legacy eeprom file has size corresponding with the chip's memory area
size in bytes.

Best regards,
Bartosz Golaszewski

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-01-29 13:10   ` Bartosz Golaszewski
@ 2016-02-02  2:28     ` Andrew Lunn
  2016-02-12  9:16     ` Andrew Lunn
  1 sibling, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2016-02-02  2:28 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: GregKH, Srinivas Kandagatla, Maxime Ripard, Wolfram Sang,
	broonie, vz, fd, LKML, Pantelis Antoniou

> Hi Andrew,
> 
> the patch works, but I'm hitting the following BUG when instantiating
> an at24c32 device:
> 
> # echo 24c32 0x54 > /sys/class/i2c-adapter/i2c-2/new_device

Ah, i did'n't tests it this way. I have my devices in device tree.

Thanks for the report. I will reproduce this in the next few days and
see about fixing it.

       Andrew

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-01-29 13:10   ` Bartosz Golaszewski
  2016-02-02  2:28     ` Andrew Lunn
@ 2016-02-12  9:16     ` Andrew Lunn
  2016-02-12 11:02       ` Bartosz Golaszewski
  1 sibling, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2016-02-12  9:16 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: GregKH, Srinivas Kandagatla, Maxime Ripard, Wolfram Sang,
	broonie, vz, fd, LKML, Pantelis Antoniou

On Fri, Jan 29, 2016 at 02:10:17PM +0100, Bartosz Golaszewski wrote:
> Hi Andrew,
> 
> the patch works, but I'm hitting the following BUG when instantiating
> an at24c32 device:

Hi Bortosz

Sorry for taking so long to get back to you. Can you confirm you had
lockdep turned on.

Thanks
	Andrew

> 
> # echo 24c32 0x54 > /sys/class/i2c-adapter/i2c-2/new_device
> [    3.741893] BUG: key de753e8c not in .data!
> [    3.749166] ------------[ cut here ]------------
> [    3.756649] WARNING: CPU: 0 PID: 102 at
> kernel/locking/lockdep.c:3002 __kernfs_create_file+0x60/0xc4()
> [    3.769048] DEBUG_LOCKS_WARN_ON(1)
> [    3.772463] Modules linked in: at24(+) nvmem_core cpufreq_dt
> omap_wdt thermal_sys leds_gpio led_class hwmon
> [    3.788301] CPU: 0 PID: 102 Comm: udevd Not tainted 4.5.0-rc1-acme+ #7
> [    3.797833] Hardware name: Generic AM33XX (Flattened Device Tree)
> [    3.806920] [<c0017d44>] (unwind_backtrace) from [<c0014034>]
> (show_stack+0x10/0x14)
> [    3.817762] [<c0014034>] (show_stack) from [<c036b478>]
> (dump_stack+0x84/0x9c)
> [    3.828071] [<c036b478>] (dump_stack) from [<c003c850>]
> (warn_slowpath_common+0x7c/0xb8)
> [    3.839284] [<c003c850>] (warn_slowpath_common) from [<c003c8bc>]
> (warn_slowpath_fmt+0x30/0x40)
> [    3.851154] [<c003c8bc>] (warn_slowpath_fmt) from [<c01fbf3c>]
> (__kernfs_create_file+0x60/0xc4)
> [    3.863025] [<c01fbf3c>] (__kernfs_create_file) from [<c01fc794>]
> (sysfs_add_file_mode_ns+0x98/0x1bc)
> [    3.875488] [<c01fc794>] (sysfs_add_file_mode_ns) from [<c01fca40>]
> (sysfs_create_bin_file+0x38/0x44)
> [    3.888000] [<c01fca40>] (sysfs_create_bin_file) from [<bf033770>]
> (nvmem_register+0x2cc/0x34c [nvmem_core])
> [    3.901190] [<bf033770>] (nvmem_register [nvmem_core]) from
> [<bf03c958>] (at24_probe+0x430/0x59c [at24])
> [    3.914055] [<bf03c958>] (at24_probe [at24]) from [<c054be80>]
> (i2c_device_probe+0x168/0x1fc)
> [    3.925926] [<c054be80>] (i2c_device_probe) from [<c045ba44>]
> (driver_probe_device+0x208/0x2c0)
> [    3.938003] [<c045ba44>] (driver_probe_device) from [<c045bb90>]
> (__driver_attach+0x94/0x98)
> [    3.949821] [<c045bb90>] (__driver_attach) from [<c0459d80>]
> (bus_for_each_dev+0x6c/0xa0)
> [    3.961373] [<c0459d80>] (bus_for_each_dev) from [<c045b038>]
> (bus_add_driver+0x18c/0x214)
> [    3.973037] [<c045b038>] (bus_add_driver) from [<c045c4f4>]
> (driver_register+0x78/0xf8)
> [    3.984458] [<c045c4f4>] (driver_register) from [<c054ca00>]
> (i2c_register_driver+0x2c/0x80)
> [    3.996349] [<c054ca00>] (i2c_register_driver) from [<c0009804>]
> (do_one_initcall+0x80/0x1e0)
> [    4.008344] [<c0009804>] (do_one_initcall) from [<c0123110>]
> (do_init_module+0x5c/0x1d4)
> [    4.019910] [<c0123110>] (do_init_module) from [<c00cb2e4>]
> (load_module+0x1cc0/0x1f48)
> [    4.031378] [<c00cb2e4>] (load_module) from [<c00cb71c>]
> (SyS_finit_module+0x64/0x74)
> [    4.042665] [<c00cb71c>] (SyS_finit_module) from [<c000f820>]
> (ret_fast_syscall+0x0/0x1c)
> [    4.054322] ---[ end trace 692db3ff57b96549 ]---
> [    4.062228] at24 2-0054: 4096 byte 24c32 EEPROM, writable, 1 bytes/write
> [    4.073224] i2c i2c-2: new_device: Instantiated device 24c32 at 0x54
> 
> It seems to result in the nvmem attribute having 0 size while the
> legacy eeprom file has size corresponding with the chip's memory area
> size in bytes.
> 
> Best regards,
> Bartosz Golaszewski

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-02-12  9:16     ` Andrew Lunn
@ 2016-02-12 11:02       ` Bartosz Golaszewski
  0 siblings, 0 replies; 12+ messages in thread
From: Bartosz Golaszewski @ 2016-02-12 11:02 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, Srinivas Kandagatla, Maxime Ripard, Wolfram Sang,
	broonie, vz, fd, LKML, Pantelis Antoniou

2016-02-12 10:16 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
> On Fri, Jan 29, 2016 at 02:10:17PM +0100, Bartosz Golaszewski wrote:
>> Hi Andrew,
>>
>> the patch works, but I'm hitting the following BUG when instantiating
>> an at24c32 device:
>
> Hi Bortosz
>
> Sorry for taking so long to get back to you. Can you confirm you had
> lockdep turned on.

Yes, this is from the config I used:

CONFIG_LOCKDEP_SUPPORT=y
CONFIG_LOCKDEP=y
# CONFIG_DEBUG_LOCKDEP is not set

Best regards,
Bartosz Golaszewski

> Thanks
>         Andrew
>
>>
>> # echo 24c32 0x54 > /sys/class/i2c-adapter/i2c-2/new_device
>> [    3.741893] BUG: key de753e8c not in .data!
>> [    3.749166] ------------[ cut here ]------------
>> [    3.756649] WARNING: CPU: 0 PID: 102 at
>> kernel/locking/lockdep.c:3002 __kernfs_create_file+0x60/0xc4()
>> [    3.769048] DEBUG_LOCKS_WARN_ON(1)
>> [    3.772463] Modules linked in: at24(+) nvmem_core cpufreq_dt
>> omap_wdt thermal_sys leds_gpio led_class hwmon
>> [    3.788301] CPU: 0 PID: 102 Comm: udevd Not tainted 4.5.0-rc1-acme+ #7
>> [    3.797833] Hardware name: Generic AM33XX (Flattened Device Tree)
>> [    3.806920] [<c0017d44>] (unwind_backtrace) from [<c0014034>]
>> (show_stack+0x10/0x14)
>> [    3.817762] [<c0014034>] (show_stack) from [<c036b478>]
>> (dump_stack+0x84/0x9c)
>> [    3.828071] [<c036b478>] (dump_stack) from [<c003c850>]
>> (warn_slowpath_common+0x7c/0xb8)
>> [    3.839284] [<c003c850>] (warn_slowpath_common) from [<c003c8bc>]
>> (warn_slowpath_fmt+0x30/0x40)
>> [    3.851154] [<c003c8bc>] (warn_slowpath_fmt) from [<c01fbf3c>]
>> (__kernfs_create_file+0x60/0xc4)
>> [    3.863025] [<c01fbf3c>] (__kernfs_create_file) from [<c01fc794>]
>> (sysfs_add_file_mode_ns+0x98/0x1bc)
>> [    3.875488] [<c01fc794>] (sysfs_add_file_mode_ns) from [<c01fca40>]
>> (sysfs_create_bin_file+0x38/0x44)
>> [    3.888000] [<c01fca40>] (sysfs_create_bin_file) from [<bf033770>]
>> (nvmem_register+0x2cc/0x34c [nvmem_core])
>> [    3.901190] [<bf033770>] (nvmem_register [nvmem_core]) from
>> [<bf03c958>] (at24_probe+0x430/0x59c [at24])
>> [    3.914055] [<bf03c958>] (at24_probe [at24]) from [<c054be80>]
>> (i2c_device_probe+0x168/0x1fc)
>> [    3.925926] [<c054be80>] (i2c_device_probe) from [<c045ba44>]
>> (driver_probe_device+0x208/0x2c0)
>> [    3.938003] [<c045ba44>] (driver_probe_device) from [<c045bb90>]
>> (__driver_attach+0x94/0x98)
>> [    3.949821] [<c045bb90>] (__driver_attach) from [<c0459d80>]
>> (bus_for_each_dev+0x6c/0xa0)
>> [    3.961373] [<c0459d80>] (bus_for_each_dev) from [<c045b038>]
>> (bus_add_driver+0x18c/0x214)
>> [    3.973037] [<c045b038>] (bus_add_driver) from [<c045c4f4>]
>> (driver_register+0x78/0xf8)
>> [    3.984458] [<c045c4f4>] (driver_register) from [<c054ca00>]
>> (i2c_register_driver+0x2c/0x80)
>> [    3.996349] [<c054ca00>] (i2c_register_driver) from [<c0009804>]
>> (do_one_initcall+0x80/0x1e0)
>> [    4.008344] [<c0009804>] (do_one_initcall) from [<c0123110>]
>> (do_init_module+0x5c/0x1d4)
>> [    4.019910] [<c0123110>] (do_init_module) from [<c00cb2e4>]
>> (load_module+0x1cc0/0x1f48)
>> [    4.031378] [<c00cb2e4>] (load_module) from [<c00cb71c>]
>> (SyS_finit_module+0x64/0x74)
>> [    4.042665] [<c00cb71c>] (SyS_finit_module) from [<c000f820>]
>> (ret_fast_syscall+0x0/0x1c)
>> [    4.054322] ---[ end trace 692db3ff57b96549 ]---
>> [    4.062228] at24 2-0054: 4096 byte 24c32 EEPROM, writable, 1 bytes/write
>> [    4.073224] i2c i2c-2: new_device: Instantiated device 24c32 at 0x54
>>
>> It seems to result in the nvmem attribute having 0 size while the
>> legacy eeprom file has size corresponding with the chip's memory area
>> size in bytes.
>>
>> Best regards,
>> Bartosz Golaszewski

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2016-02-12 11:02 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-28 15:42 [PATCH 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
2016-01-28 15:42 ` [PATCH 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
2016-01-28 15:42 ` [PATCH 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers Andrew Lunn
2016-01-28 15:42 ` [PATCH 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
2016-01-29 13:10   ` Bartosz Golaszewski
2016-02-02  2:28     ` Andrew Lunn
2016-02-12  9:16     ` Andrew Lunn
2016-02-12 11:02       ` Bartosz Golaszewski
2016-01-28 15:42 ` [PATCH 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
2016-01-28 15:42 ` [PATCH 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
2016-01-28 15:42 ` [PATCH 6/7] eeprom: 93xx46: " Andrew Lunn
2016-01-28 15:42 ` [PATCH 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.