Commit b6c217ab authored by Andrew Lunn's avatar Andrew Lunn Committed by Greg Kroah-Hartman

nvmem: Add backwards compatibility support for older EEPROM drivers.

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: default avatarAndrew Lunn <andrew@lunn.ch>
Acked-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 811b0d65
...@@ -38,8 +38,13 @@ struct nvmem_device { ...@@ -38,8 +38,13 @@ struct nvmem_device {
int users; int users;
size_t size; size_t size;
bool read_only; bool read_only;
int flags;
struct bin_attribute eeprom;
struct device *base_dev;
}; };
#define FLAG_COMPAT BIT(0)
struct nvmem_cell { struct nvmem_cell {
const char *name; const char *name;
int offset; int offset;
...@@ -56,16 +61,26 @@ static DEFINE_IDA(nvmem_ida); ...@@ -56,16 +61,26 @@ static DEFINE_IDA(nvmem_ida);
static LIST_HEAD(nvmem_cells); static LIST_HEAD(nvmem_cells);
static DEFINE_MUTEX(nvmem_cells_mutex); static DEFINE_MUTEX(nvmem_cells_mutex);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key eeprom_lock_key;
#endif
#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev) #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj, static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, struct bin_attribute *attr,
char *buf, loff_t pos, size_t count) char *buf, loff_t pos, size_t count)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev;
struct nvmem_device *nvmem = to_nvmem_device(dev); struct nvmem_device *nvmem;
int rc; 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 */ /* Stop the user from reading */
if (pos >= nvmem->size) if (pos >= nvmem->size)
return 0; return 0;
...@@ -90,10 +105,16 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj, ...@@ -90,10 +105,16 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, struct bin_attribute *attr,
char *buf, loff_t pos, size_t count) char *buf, loff_t pos, size_t count)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev;
struct nvmem_device *nvmem = to_nvmem_device(dev); struct nvmem_device *nvmem;
int rc; 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 */ /* Stop the user from writing */
if (pos >= nvmem->size) if (pos >= nvmem->size)
return 0; return 0;
...@@ -349,6 +370,43 @@ static int nvmem_add_cells(struct nvmem_device *nvmem, ...@@ -349,6 +370,43 @@ static int nvmem_add_cells(struct nvmem_device *nvmem,
return rval; 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;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
nvmem->eeprom.attr.key = &eeprom_lock_key;
#endif
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. * nvmem_register() - Register a nvmem device for given nvmem_config.
* Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
...@@ -416,16 +474,23 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) ...@@ -416,16 +474,23 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
rval = device_add(&nvmem->dev); rval = device_add(&nvmem->dev);
if (rval) { if (rval)
ida_simple_remove(&nvmem_ida, nvmem->id); goto out;
kfree(nvmem);
return ERR_PTR(rval); if (config->compat) {
rval = nvmem_setup_compat(nvmem, config);
if (rval)
goto out;
} }
if (config->cells) if (config->cells)
nvmem_add_cells(nvmem, config); nvmem_add_cells(nvmem, config);
return nvmem; return nvmem;
out:
ida_simple_remove(&nvmem_ida, nvmem->id);
kfree(nvmem);
return ERR_PTR(rval);
} }
EXPORT_SYMBOL_GPL(nvmem_register); EXPORT_SYMBOL_GPL(nvmem_register);
...@@ -445,6 +510,9 @@ int nvmem_unregister(struct nvmem_device *nvmem) ...@@ -445,6 +510,9 @@ int nvmem_unregister(struct nvmem_device *nvmem)
} }
mutex_unlock(&nvmem_mutex); mutex_unlock(&nvmem_mutex);
if (nvmem->flags & FLAG_COMPAT)
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
nvmem_device_remove_all_cells(nvmem); nvmem_device_remove_all_cells(nvmem);
device_del(&nvmem->dev); device_del(&nvmem->dev);
......
...@@ -24,6 +24,9 @@ struct nvmem_config { ...@@ -24,6 +24,9 @@ struct nvmem_config {
int ncells; int ncells;
bool read_only; bool read_only;
bool root_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) #if IS_ENABLED(CONFIG_NVMEM)
...@@ -44,5 +47,4 @@ static inline int nvmem_unregister(struct nvmem_device *nvmem) ...@@ -44,5 +47,4 @@ static inline int nvmem_unregister(struct nvmem_device *nvmem)
} }
#endif /* CONFIG_NVMEM */ #endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment