1 From b6c217ab9be6895384cf0b284ace84ad79e5c53b Mon Sep 17 00:00:00 2001
2 From: Andrew Lunn <andrew@lunn.ch>
3 Date: Fri, 26 Feb 2016 20:59:19 +0100
4 Subject: nvmem: Add backwards compatibility support for older EEPROM drivers.
6 Older drivers made an 'eeprom' file available in the /sys device
7 directory. Have the NVMEM core provide this to retain backwards
10 Signed-off-by: Andrew Lunn <andrew@lunn.ch>
11 Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
12 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
14 drivers/nvmem/core.c | 84 ++++++++++++++++++++++++++++++++++++++----
15 include/linux/nvmem-provider.h | 4 +-
16 2 files changed, 79 insertions(+), 9 deletions(-)
18 --- a/drivers/nvmem/core.c
19 +++ b/drivers/nvmem/core.c
20 @@ -38,8 +38,13 @@ struct nvmem_device {
25 + struct bin_attribute eeprom;
26 + struct device *base_dev;
29 +#define FLAG_COMPAT BIT(0)
34 @@ -56,16 +61,26 @@ static DEFINE_IDA(nvmem_ida);
35 static LIST_HEAD(nvmem_cells);
36 static DEFINE_MUTEX(nvmem_cells_mutex);
38 +#ifdef CONFIG_DEBUG_LOCK_ALLOC
39 +static struct lock_class_key eeprom_lock_key;
42 #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
44 static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
45 struct bin_attribute *attr,
46 char *buf, loff_t pos, size_t count)
48 - struct device *dev = container_of(kobj, struct device, kobj);
49 - struct nvmem_device *nvmem = to_nvmem_device(dev);
51 + struct nvmem_device *nvmem;
55 + dev = attr->private;
57 + dev = container_of(kobj, struct device, kobj);
58 + nvmem = to_nvmem_device(dev);
60 /* Stop the user from reading */
61 if (pos >= nvmem->size)
63 @@ -90,10 +105,16 @@ static ssize_t bin_attr_nvmem_write(stru
64 struct bin_attribute *attr,
65 char *buf, loff_t pos, size_t count)
67 - struct device *dev = container_of(kobj, struct device, kobj);
68 - struct nvmem_device *nvmem = to_nvmem_device(dev);
70 + struct nvmem_device *nvmem;
74 + dev = attr->private;
76 + dev = container_of(kobj, struct device, kobj);
77 + nvmem = to_nvmem_device(dev);
79 /* Stop the user from writing */
80 if (pos >= nvmem->size)
82 @@ -349,6 +370,43 @@ err:
87 + * nvmem_setup_compat() - Create an additional binary entry in
88 + * drivers sys directory, to be backwards compatible with the older
89 + * drivers/misc/eeprom drivers.
91 +static int nvmem_setup_compat(struct nvmem_device *nvmem,
92 + const struct nvmem_config *config)
96 + if (!config->base_dev)
99 + if (nvmem->read_only)
100 + nvmem->eeprom = bin_attr_ro_root_nvmem;
102 + nvmem->eeprom = bin_attr_rw_root_nvmem;
103 + nvmem->eeprom.attr.name = "eeprom";
104 + nvmem->eeprom.size = nvmem->size;
105 +#ifdef CONFIG_DEBUG_LOCK_ALLOC
106 + nvmem->eeprom.attr.key = &eeprom_lock_key;
108 + nvmem->eeprom.private = &nvmem->dev;
109 + nvmem->base_dev = config->base_dev;
111 + rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
113 + dev_err(&nvmem->dev,
114 + "Failed to create eeprom binary file %d\n", rval);
118 + nvmem->flags |= FLAG_COMPAT;
124 * nvmem_register() - Register a nvmem device for given nvmem_config.
125 * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
126 @@ -416,16 +474,23 @@ struct nvmem_device *nvmem_register(cons
127 dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
129 rval = device_add(&nvmem->dev);
131 - ida_simple_remove(&nvmem_ida, nvmem->id);
133 - return ERR_PTR(rval);
137 + if (config->compat) {
138 + rval = nvmem_setup_compat(nvmem, config);
144 nvmem_add_cells(nvmem, config);
148 + ida_simple_remove(&nvmem_ida, nvmem->id);
150 + return ERR_PTR(rval);
152 EXPORT_SYMBOL_GPL(nvmem_register);
154 @@ -445,6 +510,9 @@ int nvmem_unregister(struct nvmem_device
156 mutex_unlock(&nvmem_mutex);
158 + if (nvmem->flags & FLAG_COMPAT)
159 + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
161 nvmem_device_remove_all_cells(nvmem);
162 device_del(&nvmem->dev);
164 --- a/include/linux/nvmem-provider.h
165 +++ b/include/linux/nvmem-provider.h
166 @@ -24,6 +24,9 @@ struct nvmem_config {
170 + /* To be only used by old driver/misc/eeprom drivers */
172 + struct device *base_dev;
175 #if IS_ENABLED(CONFIG_NVMEM)
176 @@ -44,5 +47,4 @@ static inline int nvmem_unregister(struc
179 #endif /* CONFIG_NVMEM */
181 #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */