aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvmem/core.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2016-02-26 14:59:19 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-03-01 19:55:48 -0500
commitb6c217ab9be6895384cf0b284ace84ad79e5c53b (patch)
tree5e41a05bde354301b9b8ebe9ed6d56e57c53f4eb /drivers/nvmem/core.c
parent811b0d6538b9f26f3eb0f90fe4e6118f2480ec6f (diff)
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: Andrew Lunn <andrew@lunn.ch> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/nvmem/core.c')
-rw-r--r--drivers/nvmem/core.c84
1 files changed, 76 insertions, 8 deletions
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index b03690bc8f09..0de3d878c439 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -38,8 +38,13 @@ struct nvmem_device {
38 int users; 38 int users;
39 size_t size; 39 size_t size;
40 bool read_only; 40 bool read_only;
41 int flags;
42 struct bin_attribute eeprom;
43 struct device *base_dev;
41}; 44};
42 45
46#define FLAG_COMPAT BIT(0)
47
43struct nvmem_cell { 48struct nvmem_cell {
44 const char *name; 49 const char *name;
45 int offset; 50 int offset;
@@ -56,16 +61,26 @@ static DEFINE_IDA(nvmem_ida);
56static LIST_HEAD(nvmem_cells); 61static LIST_HEAD(nvmem_cells);
57static DEFINE_MUTEX(nvmem_cells_mutex); 62static DEFINE_MUTEX(nvmem_cells_mutex);
58 63
64#ifdef CONFIG_DEBUG_LOCK_ALLOC
65static struct lock_class_key eeprom_lock_key;
66#endif
67
59#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev) 68#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
60 69
61static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj, 70static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
62 struct bin_attribute *attr, 71 struct bin_attribute *attr,
63 char *buf, loff_t pos, size_t count) 72 char *buf, loff_t pos, size_t count)
64{ 73{
65 struct device *dev = container_of(kobj, struct device, kobj); 74 struct device *dev;
66 struct nvmem_device *nvmem = to_nvmem_device(dev); 75 struct nvmem_device *nvmem;
67 int rc; 76 int rc;
68 77
78 if (attr->private)
79 dev = attr->private;
80 else
81 dev = container_of(kobj, struct device, kobj);
82 nvmem = to_nvmem_device(dev);
83
69 /* Stop the user from reading */ 84 /* Stop the user from reading */
70 if (pos >= nvmem->size) 85 if (pos >= nvmem->size)
71 return 0; 86 return 0;
@@ -90,10 +105,16 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
90 struct bin_attribute *attr, 105 struct bin_attribute *attr,
91 char *buf, loff_t pos, size_t count) 106 char *buf, loff_t pos, size_t count)
92{ 107{
93 struct device *dev = container_of(kobj, struct device, kobj); 108 struct device *dev;
94 struct nvmem_device *nvmem = to_nvmem_device(dev); 109 struct nvmem_device *nvmem;
95 int rc; 110 int rc;
96 111
112 if (attr->private)
113 dev = attr->private;
114 else
115 dev = container_of(kobj, struct device, kobj);
116 nvmem = to_nvmem_device(dev);
117
97 /* Stop the user from writing */ 118 /* Stop the user from writing */
98 if (pos >= nvmem->size) 119 if (pos >= nvmem->size)
99 return 0; 120 return 0;
@@ -349,6 +370,43 @@ err:
349 return rval; 370 return rval;
350} 371}
351 372
373/*
374 * nvmem_setup_compat() - Create an additional binary entry in
375 * drivers sys directory, to be backwards compatible with the older
376 * drivers/misc/eeprom drivers.
377 */
378static int nvmem_setup_compat(struct nvmem_device *nvmem,
379 const struct nvmem_config *config)
380{
381 int rval;
382
383 if (!config->base_dev)
384 return -EINVAL;
385
386 if (nvmem->read_only)
387 nvmem->eeprom = bin_attr_ro_root_nvmem;
388 else
389 nvmem->eeprom = bin_attr_rw_root_nvmem;
390 nvmem->eeprom.attr.name = "eeprom";
391 nvmem->eeprom.size = nvmem->size;
392#ifdef CONFIG_DEBUG_LOCK_ALLOC
393 nvmem->eeprom.attr.key = &eeprom_lock_key;
394#endif
395 nvmem->eeprom.private = &nvmem->dev;
396 nvmem->base_dev = config->base_dev;
397
398 rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
399 if (rval) {
400 dev_err(&nvmem->dev,
401 "Failed to create eeprom binary file %d\n", rval);
402 return rval;
403 }
404
405 nvmem->flags |= FLAG_COMPAT;
406
407 return 0;
408}
409
352/** 410/**
353 * nvmem_register() - Register a nvmem device for given nvmem_config. 411 * nvmem_register() - Register a nvmem device for given nvmem_config.
354 * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem 412 * 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 dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); 474 dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
417 475
418 rval = device_add(&nvmem->dev); 476 rval = device_add(&nvmem->dev);
419 if (rval) { 477 if (rval)
420 ida_simple_remove(&nvmem_ida, nvmem->id); 478 goto out;
421 kfree(nvmem); 479
422 return ERR_PTR(rval); 480 if (config->compat) {
481 rval = nvmem_setup_compat(nvmem, config);
482 if (rval)
483 goto out;
423 } 484 }
424 485
425 if (config->cells) 486 if (config->cells)
426 nvmem_add_cells(nvmem, config); 487 nvmem_add_cells(nvmem, config);
427 488
428 return nvmem; 489 return nvmem;
490out:
491 ida_simple_remove(&nvmem_ida, nvmem->id);
492 kfree(nvmem);
493 return ERR_PTR(rval);
429} 494}
430EXPORT_SYMBOL_GPL(nvmem_register); 495EXPORT_SYMBOL_GPL(nvmem_register);
431 496
@@ -445,6 +510,9 @@ int nvmem_unregister(struct nvmem_device *nvmem)
445 } 510 }
446 mutex_unlock(&nvmem_mutex); 511 mutex_unlock(&nvmem_mutex);
447 512
513 if (nvmem->flags & FLAG_COMPAT)
514 device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
515
448 nvmem_device_remove_all_cells(nvmem); 516 nvmem_device_remove_all_cells(nvmem);
449 device_del(&nvmem->dev); 517 device_del(&nvmem->dev);
450 518